Compare commits

...

436 Commits

Author SHA1 Message Date
David Peter
9b93739045 Make symbol_by_id a query again 2025-02-20 17:29:58 +01:00
Micha Reiser
6c28afda8b Untrack symbol_by_id 2025-02-20 17:29:58 +01:00
David Peter
2525b076e9 Use or_fall_back_to 2025-02-20 17:29:58 +01:00
David Peter
1d757ce9ee Use __kwdefaults__ instead of __module__ 2025-02-20 17:29:58 +01:00
David Peter
4c38c761f7 Attempt to model getattr_static on gradual types 2025-02-20 17:29:58 +01:00
David Peter
0fa827fa32 Model fallback MethodType => FunctionType 2025-02-20 17:29:58 +01:00
David Peter
8a08325b9a Remove incorrect __class__ lookup branch in static_member 2025-02-20 17:29:58 +01:00
David Peter
3f65f8a4bd Add doc comment for try_call_dunder_get 2025-02-20 17:29:58 +01:00
David Peter
e9597712e7 Add TODO for builtins.tuple attribute lookups 2025-02-20 17:29:58 +01:00
David Peter
8978a4c994 Add FunctionLiteral and BoundMethod to property tests 2025-02-20 17:29:58 +01:00
David Peter
3eea6b44ea Wording 2025-02-20 17:29:58 +01:00
David Peter
49f404c4df Add TODO: Type::member should return Result 2025-02-20 17:29:58 +01:00
David Peter
5807aed630 Return a Result from try_call_dunder_get 2025-02-20 17:29:58 +01:00
David Peter
0074a54259 Add reference to 'Functions and methods' section in the descriptor guide 2025-02-20 17:29:58 +01:00
David Peter
9a5ba282c9 Properly catch errors to known function calls 2025-02-20 17:29:58 +01:00
David Peter
1437639963 Wording and typos 2025-02-20 17:29:58 +01:00
David Peter
c3cc3815f4 Introduce CallArguments::none() 2025-02-20 17:29:58 +01:00
David Peter
c5998afdc1 Fix two typos 2025-02-20 17:29:58 +01:00
David Peter
77adc44c6f Remove memoryview as a KnownClass 2025-02-20 17:29:58 +01:00
David Peter
663e7ef22b Fix clippy suggestion 2025-02-20 17:29:58 +01:00
David Peter
96a6727daf Handle errors in __get__ calls 2025-02-20 17:29:58 +01:00
David Peter
137a8eb82f Use write!(…) 2025-02-20 17:29:58 +01:00
David Peter
24749ef645 Patch is_assignable_to to add partial support for SupportsIndex 2025-02-20 17:29:58 +01:00
David Peter
886976cd47 [red-knot] Method calls and descriptor protocol 2025-02-20 17:29:58 +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
Alex Waygood
fbb06fe0ac [red-knot] Small simplifications to Type::is_subtype_of and Type::is_disjoint_from (#15622)
## Summary

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

## Test Plan

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

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

## Test Plan

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

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

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

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

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

## Test Plan

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

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

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

## Test Plan

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

## Summary

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

## Test Plan

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

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

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

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

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

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

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

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

## Test Plan

- Tested the new runner under various scenarios.

---------

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

Resolves #6447.

## Test Plan

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

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

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

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

## Test Plan

—

---------

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

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

## Summary

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

## Test Plan

<!-- How was it tested? -->
2025-01-20 10:57:21 +01:00
renovate[bot]
36c90ebe86 Update Rust crate notify to v8 (#15435)
This PR contains the following updates:

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

---

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

---

### Release Notes

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

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

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

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

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

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

</details>

---

### Configuration

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

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

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

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

---

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

---

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

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

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 10:41:16 +01:00
Wei Lee
cbf9b66fc1 [airflow] Extend AIR303 with more symbols (#15611)
## Summary

Extend `AIR303` with the following rules

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

## Test Plan

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

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

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

## Test Plan

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

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

## Test Plan

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

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

Resolves #15522.

## Test Plan

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

---------

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

Move `type_alias_types` test to Markdown

## Test Plan

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

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

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

## Test Plan

Markdown tests.
2025-01-20 08:42:22 +01:00
Dhruv Manilawala
d97502d647 Include more labels in CHANGELOG sections (#15566)
## Summary

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

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

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

---

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

---

### Release Notes

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

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

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

##### 🚀 Features

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

##### 🩹 Fixes

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

##### ❤️ Thank You

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

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

</details>

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

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

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

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

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

</details>

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

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

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

### eslint-config-prettier

#### 10.0.1

#### What's Changed

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

#### New Contributors

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

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

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

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

##### Major Changes

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

</details>

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

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

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

##### Fixed

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

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

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

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

</details>

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

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

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

##### Patch Changes

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

</details>

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

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

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

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

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

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

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

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

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

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

```

#### Thanks to Sponsors

This release was possible thanks to our community.

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

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

</details>

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

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

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

##### Patch Changes

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

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

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

##### Patch Changes

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

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

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

##### Minor Changes

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

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

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

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

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

##### Minor Changes

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

##### Patch Changes

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

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

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

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

</details>

---

### Configuration

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

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

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

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

---

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

---

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

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

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

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

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

---

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

---

### Release Notes

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

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

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

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

</details>

---

### Configuration

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

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

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

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

---

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

---

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

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

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-20 10:18:43 +05:30
renovate[bot]
c0383daf58 Update Rust crate similar to v2.7.0 (#15602) 2025-01-19 22:46:45 -05:00
renovate[bot]
780335b50d Update Rust crate uuid to v1.12.0 (#15599) 2025-01-19 22:45:12 -05:00
renovate[bot]
07f2308557 Update cloudflare/wrangler-action action to v3.13.1 (#15594) 2025-01-19 22:31:47 -05:00
renovate[bot]
06d9f8ba00 Update Rust crate tracing-indicatif to v0.3.9 (#15593) 2025-01-19 22:31:38 -05:00
renovate[bot]
57a84a3354 Update dependency ruff to v0.9.2 (#15595) 2025-01-19 22:31:26 -05:00
renovate[bot]
b49dee0959 Update Rust crate bitflags to v2.8.0 (#15597) 2025-01-19 22:31:19 -05:00
renovate[bot]
68755ac1e3 Update Rust crate ordermap to v0.5.5 (#15591) 2025-01-19 22:31:02 -05:00
renovate[bot]
b9402688b1 Update Rust crate serde_json to v1.0.137 (#15592) 2025-01-19 22:30:54 -05:00
renovate[bot]
75eccfd2a2 Update Rust crate log to v0.4.25 (#15590) 2025-01-19 22:30:32 -05:00
renovate[bot]
3c043e7e70 Update Rust crate indexmap to v2.7.1 (#15589) 2025-01-19 22:30:24 -05:00
Charlie Marsh
98fccec2e7 Avoid removing too many imports in redefined-while-unused (#15585)
## Summary

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

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

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

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

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

Closes #15504 

## Test Plan

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

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

---------

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

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

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

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

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

---------

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

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

class Parent(Grandparent): ...

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

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

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

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

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

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

class C:
    x: ClassVar[int] = 1

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

## Test Plan

- New tests for the `typing.ClassVar` qualifier
- Fixed one TODO in `attributes.md`
2025-01-18 13:51:35 +01:00
InSync
9730ff3a25 Generate documentation redirects for lowercase rule codes (#15564)
## Summary

Resolves #15016.

## Test Plan

Generate the docs with:

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

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

```console
uvx --with-requirements docs/requirements-insiders.txt -- mkdocs serve -f mkdocs.insiders.yml -o
```
2025-01-18 10:09:23 +05:30
InSync
9d845ec8f5 [red-knot] Migrate is_gradual_equivalent_to unit tests to Markdown tests (#15563)
## Summary

Part of #15397 and #15516.

## Test Plan

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

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

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

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

## Test plan

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

---------

Co-authored-by: Micha Reiser <micha@reiser.io>
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-17 14:23:02 -05:00
Alex Waygood
4351d85d24 [red-knot] Inline SubclassOfType::as_instance_type_of_metaclass() (#15556) 2025-01-17 19:01:36 +00:00
wooly18
1ba8e61875 [flake8-comprehensions] strip parentheses around generators in unnecessary-generator-set (C401) (#15553)
<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

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

## Summary

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

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

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

---------

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

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

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

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

## Test Plan

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

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

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

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

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

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

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

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

## Test Plan

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

Resolves #7127.

## Test Plan

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

Resolves #9730.

## Test Plan

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

---------

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

Resolves #15540.

## Test Plan

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

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

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

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

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

## Test Plan

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

---------

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

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

Resolves #13086

Part of #12434

## Test Plan

Run tests with setting enabled.

---------

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

---------

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

Part of #15397.

## Test Plan

Markdown tests.
2025-01-16 11:21:56 -08:00
Brent Westbrook
e2da33a45c [unconventional-import-alias] Fix infinite loop between ICN001 and I002 (ICN001) (#15480)
## Summary

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

## Test Plan

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

Closes #14389

---------

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

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

## Test Plan

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

Closes #12897

---------

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

Part of #15397.

## Test Plan

Markdown tests.

---------

Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-01-16 07:40:41 -08:00
InSync
aed0bf1c11 [ruff] itertools.starmap(..., zip(...)) (RUF058) (#15483)
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-01-16 15:18:12 +01:00
1870 changed files with 69504 additions and 30573 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"

4
.gitattributes vendored
View File

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

2
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
# This file cannot use the extension `.yaml`.
blank_issues_enabled: false

22
.github/ISSUE_TEMPLATE/issue.yaml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: New issue
description: A generic issue
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to report an issue! We're glad to have you involved with Ruff.
If you're filing a bug report, please consider including the following information:
* List of keywords you searched for before creating this issue. Write them down here so that others can find this issue more easily and help provide feedback.
e.g. "RUF001", "unused variable", "Jupyter notebook"
* A minimal code snippet that reproduces the bug.
* The command you invoked (e.g., `ruff /path/to/file.py --fix`), ideally including the `--isolated` flag.
* The current Ruff settings (any relevant sections from your `pyproject.toml`).
* The current Ruff version (`ruff --version`).
- type: textarea
attributes:
label: Description
description: A description of the issue

View File

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

View File

@@ -58,6 +58,12 @@
description: "Disable PRs updating GitHub runners (e.g. 'runs-on: macos-14')",
enabled: false,
},
{
// TODO: Remove this once the codebase is upgrade to v4 (https://github.com/astral-sh/ruff/pull/16069)
matchPackageNames: ["tailwindcss"],
matchManagers: ["npm"],
enabled: false,
},
{
// Disable updates of `zip-rs`; intentionally pinned for now due to ownership change
// See: https://github.com/astral-sh/uv/issues/3642

View File

@@ -23,6 +23,8 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions: {}
env:
PACKAGE_NAME: ruff
MODULE_NAME: ruff

View File

@@ -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

View File

@@ -1,5 +1,7 @@
name: CI
permissions: {}
on:
push:
branches: [main]
@@ -59,6 +61,7 @@ jobs:
- Cargo.toml
- Cargo.lock
- crates/**
- "!crates/red_knot*/**"
- "!crates/ruff_python_formatter/**"
- "!crates/ruff_formatter/**"
- "!crates/ruff_dev/**"
@@ -116,11 +119,11 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: Swatinem/rust-cache@v2
- 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)"
@@ -130,12 +133,13 @@ jobs:
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
with:
persist-credentials: false
- uses: Swatinem/rust-cache@v2
- name: "Install Rust toolchain"
run: rustup show
- name: "Install mold"
@@ -148,7 +152,6 @@ jobs:
uses: taiki-e/install-action@v2
with:
tool: cargo-insta
- uses: Swatinem/rust-cache@v2
- name: "Run tests"
shell: bash
env:
@@ -176,12 +179,13 @@ jobs:
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
with:
persist-credentials: false
- uses: Swatinem/rust-cache@v2
- name: "Install Rust toolchain"
run: rustup show
- name: "Install mold"
@@ -194,7 +198,6 @@ jobs:
uses: taiki-e/install-action@v2
with:
tool: cargo-insta
- uses: Swatinem/rust-cache@v2
- name: "Run tests"
shell: bash
env:
@@ -203,24 +206,25 @@ jobs:
cargo-test-windows:
name: "cargo test (windows)"
runs-on: windows-latest-xlarge
runs-on: github-windows-2025-x86_64-16
needs: determine_changes
if: ${{ needs.determine_changes.outputs.code == 'true' || github.ref == 'refs/heads/main' }}
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
with:
persist-credentials: false
- uses: Swatinem/rust-cache@v2
- name: "Install Rust toolchain"
run: rustup show
- name: "Install cargo nextest"
uses: taiki-e/install-action@v2
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,12 +235,13 @@ 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
with:
persist-credentials: false
- uses: Swatinem/rust-cache@v2
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: actions/setup-node@v4
@@ -247,7 +252,6 @@ jobs:
- uses: jetli/wasm-pack-action@v0.4.0
with:
version: v0.13.1
- uses: Swatinem/rust-cache@v2
- name: "Test ruff_wasm"
run: |
cd crates/ruff_wasm
@@ -266,19 +270,19 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: Swatinem/rust-cache@v2
- name: "Install Rust toolchain"
run: rustup show
- name: "Install mold"
uses: rui314/setup-mold@v1
- uses: Swatinem/rust-cache@v2
- 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
@@ -289,6 +293,7 @@ jobs:
with:
file: "Cargo.toml"
field: "workspace.package.rust-version"
- uses: Swatinem/rust-cache@v2
- name: "Install Rust toolchain"
env:
MSRV: ${{ steps.msrv.outputs.value }}
@@ -303,7 +308,6 @@ jobs:
uses: taiki-e/install-action@v2
with:
tool: cargo-insta
- uses: Swatinem/rust-cache@v2
- name: "Run tests"
shell: bash
env:
@@ -321,11 +325,11 @@ jobs:
- uses: actions/checkout@v4
with:
persist-credentials: false
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v2
with:
workspaces: "fuzz -> target"
- name: "Install Rust toolchain"
run: rustup show
- name: "Install cargo-binstall"
uses: cargo-bins/cargo-binstall@main
with:
@@ -341,7 +345,7 @@ 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
@@ -377,15 +381,21 @@ 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
with:
persist-credentials: false
- uses: Swatinem/rust-cache@v2
- name: "Install Rust toolchain"
run: rustup component add rustfmt
- uses: Swatinem/rust-cache@v2
# Run all code generation scripts, and verify that the current output is
# already checked into git.
- run: python crates/ruff_python_ast/generate.py
- run: python crates/ruff_python_formatter/generate.py
- run: test -z "$(git status --porcelain)"
# Verify that adding a plugin or rule produces clean code.
- run: ./scripts/add_rule.py --name DoTheThing --prefix F --code 999 --linter pyflakes
- run: cargo check
- run: cargo fmt --all --check
@@ -403,7 +413,7 @@ 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
@@ -420,7 +430,7 @@ jobs:
name: ruff
path: target/debug
- uses: dawidd6/action-download-artifact@v7
- uses: dawidd6/action-download-artifact@v8
name: Download baseline Ruff binary
with:
name: ruff
@@ -537,6 +547,7 @@ 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
with:
@@ -571,9 +582,9 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: ${{ env.PYTHON_VERSION }}
- uses: Swatinem/rust-cache@v2
- name: "Install Rust toolchain"
run: rustup show
- uses: Swatinem/rust-cache@v2
- name: "Install pre-commit"
run: pip install pre-commit
- name: "Cache pre-commit"
@@ -605,6 +616,7 @@ jobs:
- uses: actions/setup-python@v5
with:
python-version: "3.13"
- uses: Swatinem/rust-cache@v2
- name: "Add SSH key"
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}
uses: webfactory/ssh-agent@v0.9.0
@@ -614,7 +626,6 @@ jobs:
run: rustup show
- name: Install uv
uses: astral-sh/setup-uv@v5
- uses: Swatinem/rust-cache@v2
- name: "Install Insiders dependencies"
if: ${{ env.MKDOCS_INSIDERS_SSH_KEY_EXISTS == 'true' }}
run: uv pip install -r docs/requirements-insiders.txt --system
@@ -638,16 +649,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
with:
persist-credentials: false
- uses: Swatinem/rust-cache@v2
- 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"
@@ -662,7 +672,7 @@ 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
env:
@@ -702,9 +712,9 @@ jobs:
just test
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"
@@ -712,6 +722,8 @@ jobs:
with:
persist-credentials: false
- uses: Swatinem/rust-cache@v2
- name: "Install Rust toolchain"
run: rustup show
@@ -720,8 +732,6 @@ jobs:
with:
tool: cargo-codspeed
- uses: Swatinem/rust-cache@v2
- name: "Build benchmarks"
run: cargo codspeed build --features codspeed -p ruff_benchmark

View File

@@ -16,7 +16,7 @@ jobs:
permissions:
pull-requests: write
steps:
- uses: dawidd6/action-download-artifact@v7
- uses: dawidd6/action-download-artifact@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@v8
name: "Download ecosystem results"
id: download-ecosystem-result
if: steps.pr-number.outputs.pr-number

View File

@@ -35,6 +35,8 @@ jobs:
cache: "npm"
cache-dependency-path: playground/package-lock.json
- uses: jetli/wasm-pack-action@v0.4.0
with:
version: v0.13.1
- 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
@@ -49,7 +51,7 @@ jobs:
working-directory: playground
- name: "Deploy to Cloudflare Pages"
if: ${{ env.CF_API_TOKEN_EXISTS == 'true' }}
uses: cloudflare/wrangler-action@v3.13.0
uses: cloudflare/wrangler-action@v3.14.0
with:
apiToken: ${{ secrets.CF_API_TOKEN }}
accountId: ${{ secrets.CF_ACCOUNT_ID }}

View File

@@ -35,6 +35,8 @@ jobs:
- name: "Install Rust toolchain"
run: rustup target add wasm32-unknown-unknown
- uses: jetli/wasm-pack-action@v0.4.0
with:
version: v0.13.1
- uses: jetli/wasm-bindgen-action@v0.2.0
- name: "Run wasm-pack build"
run: wasm-pack build --target ${{ matrix.target }} crates/ruff_wasm

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
###

View File

@@ -4,7 +4,8 @@ exclude: |
(?x)^(
.github/workflows/release.yml|
crates/red_knot_vendored/vendor/.*|
crates/red_knot_workspace/resources/.*|
crates/red_knot_project/resources/.*|
crates/ruff_benchmark/resources/.*|
crates/ruff_linter/resources/.*|
crates/ruff_linter/src/rules/.*/snapshots/.*|
crates/ruff_notebook/resources/.*|
@@ -23,7 +24,7 @@ repos:
- id: validate-pyproject
- repo: https://github.com/executablebooks/mdformat
rev: 0.7.21
rev: 0.7.22
hooks:
- id: mdformat
additional_dependencies:
@@ -36,7 +37,7 @@ repos:
)$
- repo: https://github.com/igorshubovych/markdownlint-cli
rev: v0.43.0
rev: v0.44.0
hooks:
- id: markdownlint-fix
exclude: |
@@ -56,10 +57,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.29.7
hooks:
- id: typos
@@ -73,7 +74,7 @@ repos:
pass_filenames: false # This makes it a lot faster
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.1
rev: v0.9.6
hooks:
- id: ruff-format
- id: ruff
@@ -83,7 +84,7 @@ repos:
# Prettier
- repo: https://github.com/rbubley/mirrors-prettier
rev: v3.4.2
rev: v3.5.1
hooks:
- id: prettier
types: [yaml]
@@ -91,19 +92,19 @@ repos:
# zizmor detects security vulnerabilities in GitHub Actions workflows.
# Additional configuration for the tool is found in `.github/zizmor.yml`
- repo: https://github.com/woodruffw/zizmor-pre-commit
rev: v1.0.1
rev: v1.3.1
hooks:
- id: zizmor
- repo: https://github.com/python-jsonschema/check-jsonschema
rev: 0.31.0
rev: 0.31.1
hooks:
- id: check-github-workflows
# `actionlint` hook, for verifying correct syntax in GitHub Actions workflows.
# Some additional configuration for `actionlint` can be found in `.github/actionlint.yaml`.
- repo: https://github.com/rhysd/actionlint
rev: v1.7.6
rev: v1.7.7
hooks:
- id: actionlint
stages:

View File

@@ -209,8 +209,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,251 @@
# Changelog
## 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-comprehensions`\]: Handle trailing comma in `C403` fix ([#16110](https://github.com/astral-sh/ruff/pull/16110))
- \[`flake8-debugger`\] Also flag `sys.breakpointhook` and `sys.__breakpointhook__` (`T100`) ([#16191](https://github.com/astral-sh/ruff/pull/16191))
- \[`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))
- \[`ruff`\] Skip `RUF001` diagnostics when visiting string type definitions ([#16122](https://github.com/astral-sh/ruff/pull/16122))
- \[`flake8-pyi`\] Avoid flagging `custom-typevar-for-self` on metaclass methods (`PYI019`) ([#16141](https://github.com/astral-sh/ruff/pull/16141))
- \[`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
- \[`refurb`\] Correctly handle lengths of literal strings in `slice-to-remove-prefix-or-suffix` (`FURB188`) ([#16237](https://github.com/astral-sh/ruff/pull/16237))
### 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

View File

@@ -526,7 +526,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.
@@ -678,9 +678,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 {

1150
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@ ruff_workspace = { path = "crates/ruff_workspace" }
red_knot_python_semantic = { path = "crates/red_knot_python_semantic" }
red_knot_server = { path = "crates/red_knot_server" }
red_knot_test = { path = "crates/red_knot_test" }
red_knot_workspace = { path = "crates/red_knot_workspace", default-features = false }
red_knot_project = { path = "crates/red_knot_project", default-features = false }
aho-corasick = { version = "1.1.3" }
anstream = { version = "0.6.18" }
@@ -74,11 +74,13 @@ env_logger = { version = "0.11.0" }
etcetera = { version = "0.8.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",
] }
ignore = { version = "0.4.22" }
@@ -105,7 +107,7 @@ matchit = { version = "0.8.1" }
memchr = { version = "2.7.1" }
mimalloc = { version = "0.1.39" }
natord = { version = "1.0.9" }
notify = { version = "7.0.0" }
notify = { version = "8.0.0" }
ordermap = { version = "0.5.0" }
path-absolutize = { version = "3.1.1" }
path-slash = { version = "0.2.1" }
@@ -116,12 +118,12 @@ 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" }
# 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/salsa-rs/salsa.git", rev = "351d9cf0037be949d17800d0c7b4838e533c2ed6" }
schemars = { version = "0.8.16" }
seahash = { version = "4.1.0" }
serde = { version = "1.0.197", features = ["derive"] }
@@ -134,10 +136,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" }
@@ -159,7 +166,6 @@ 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",
@@ -173,6 +179,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"]
[workspace.lints.rust]
unsafe_code = "warn"
unreachable_pub = "warn"
@@ -305,7 +315,11 @@ 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"]
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

View File

@@ -149,8 +149,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.9.7/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.9.7/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 +183,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.9.7
hooks:
# Run the linter.
- id: ruff
@@ -452,6 +452,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

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

25
crates/red_knot/README.md Normal file
View File

@@ -0,0 +1,25 @@
# Red Knot
Red Knot is an extremely fast type checker.
Currently, it is a work-in-progress and not ready for user testing.
Red Knot is designed to prioritize good type inference, even in unannotated code,
and aims to avoid false positives.
While Red Knot will produce similar results to mypy and pyright on many codebases,
100% compatibility with these tools is a non-goal.
On some codebases, Red Knot's design decisions lead to different outcomes
than you would get from running one of these more established tools.
## Contributing
Core type checking tests are written as Markdown code blocks.
They can be found in [`red_knot_python_semantic/resources/mdtest`][resources-mdtest].
See [`red_knot_test/README.md`][mdtest-readme] for more information
on the test framework itself.
The list of open issues can be found [here][open-issues].
[mdtest-readme]: ../red_knot_test/README.md
[open-issues]: https://github.com/astral-sh/ruff/issues?q=sort%3Aupdated-desc%20is%3Aissue%20is%3Aopen%20label%3Ared-knot
[resources-mdtest]: ../red_knot_python_semantic/resources/mdtest

104
crates/red_knot/build.rs Normal file
View File

@@ -0,0 +1,104 @@
use std::{
fs,
path::{Path, PathBuf},
process::Command,
};
fn main() {
// The workspace root directory is not available without walking up the tree
// https://github.com/rust-lang/cargo/issues/3946
let workspace_root = Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
.join("..")
.join("..");
commit_info(&workspace_root);
#[allow(clippy::disallowed_methods)]
let target = std::env::var("TARGET").unwrap();
println!("cargo::rustc-env=RUST_HOST_TARGET={target}");
}
fn commit_info(workspace_root: &Path) {
// If not in a git repository, do not attempt to retrieve commit information
let git_dir = workspace_root.join(".git");
if !git_dir.exists() {
return;
}
if let Some(git_head_path) = git_head(&git_dir) {
println!("cargo:rerun-if-changed={}", git_head_path.display());
let git_head_contents = fs::read_to_string(git_head_path);
if let Ok(git_head_contents) = git_head_contents {
// The contents are either a commit or a reference in the following formats
// - "<commit>" when the head is detached
// - "ref <ref>" when working on a branch
// If a commit, checking if the HEAD file has changed is sufficient
// If a ref, we need to add the head file for that ref to rebuild on commit
let mut git_ref_parts = git_head_contents.split_whitespace();
git_ref_parts.next();
if let Some(git_ref) = git_ref_parts.next() {
let git_ref_path = git_dir.join(git_ref);
println!("cargo:rerun-if-changed={}", git_ref_path.display());
}
}
}
let output = match Command::new("git")
.arg("log")
.arg("-1")
.arg("--date=short")
.arg("--abbrev=9")
.arg("--format=%H %h %cd %(describe)")
.output()
{
Ok(output) if output.status.success() => output,
_ => return,
};
let stdout = String::from_utf8(output.stdout).unwrap();
let mut parts = stdout.split_whitespace();
let mut next = || parts.next().unwrap();
let _commit_hash = next();
println!("cargo::rustc-env=RED_KNOT_COMMIT_SHORT_HASH={}", next());
println!("cargo::rustc-env=RED_KNOT_COMMIT_DATE={}", next());
// Describe can fail for some commits
// https://git-scm.com/docs/pretty-formats#Documentation/pretty-formats.txt-emdescribeoptionsem
if let Some(describe) = parts.next() {
let mut describe_parts = describe.split('-');
let _last_tag = describe_parts.next().unwrap();
// If this is the tagged commit, this component will be missing
println!(
"cargo::rustc-env=RED_KNOT_LAST_TAG_DISTANCE={}",
describe_parts.next().unwrap_or("0")
);
}
}
fn git_head(git_dir: &Path) -> Option<PathBuf> {
// The typical case is a standard git repository.
let git_head_path = git_dir.join("HEAD");
if git_head_path.exists() {
return Some(git_head_path);
}
if !git_dir.is_file() {
return None;
}
// If `.git/HEAD` doesn't exist and `.git` is actually a file,
// then let's try to attempt to read it as a worktree. If it's
// a worktree, then its contents will look like this, e.g.:
//
// gitdir: /home/andrew/astral/uv/main/.git/worktrees/pr2
//
// And the HEAD file we want to watch will be at:
//
// /home/andrew/astral/uv/main/.git/worktrees/pr2/HEAD
let contents = fs::read_to_string(git_dir).ok()?;
let (label, worktree_path) = contents.split_once(':')?;
if label != "gitdir" {
return None;
}
let worktree_path = worktree_path.trim();
Some(PathBuf::from(worktree_path))
}

204
crates/red_knot/src/args.rs Normal file
View File

@@ -0,0 +1,204 @@
use crate::logging::Verbosity;
use crate::python_version::PythonVersion;
use clap::{ArgAction, ArgMatches, Error, Parser};
use red_knot_project::metadata::options::{EnvironmentOptions, Options, TerminalOptions};
use red_knot_project::metadata::value::{RangedValue, RelativePathBuf};
use red_knot_python_semantic::lint;
use ruff_db::system::SystemPathBuf;
#[derive(Debug, Parser)]
#[command(
author,
name = "red-knot",
about = "An extremely fast Python type checker."
)]
#[command(version)]
pub(crate) struct Args {
#[command(subcommand)]
pub(crate) command: Command,
}
#[derive(Debug, clap::Subcommand)]
pub(crate) enum Command {
/// Check a project for type errors.
Check(CheckCommand),
/// Start the language server
Server,
/// Display Red Knot's version
Version,
}
#[derive(Debug, Parser)]
pub(crate) struct CheckCommand {
/// 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")]
pub(crate) 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")]
pub(crate) venv_path: Option<SystemPathBuf>,
/// Custom directory to use for stdlib typeshed stubs.
#[arg(long, value_name = "PATH", alias = "custom-typeshed-dir")]
pub(crate) typeshed: Option<SystemPathBuf>,
/// Additional path to use as a module-resolution source (can be passed multiple times).
#[arg(long, value_name = "PATH")]
pub(crate) extra_search_path: Option<Vec<SystemPathBuf>>,
/// Python version to assume when resolving types.
#[arg(long, value_name = "VERSION", alias = "target-version")]
pub(crate) python_version: Option<PythonVersion>,
#[clap(flatten)]
pub(crate) verbosity: Verbosity,
#[clap(flatten)]
pub(crate) rules: RulesArg,
/// Use exit code 1 if there are any warning-level diagnostics.
#[arg(long, conflicts_with = "exit_zero", default_missing_value = "true", num_args=0..1)]
pub(crate) error_on_warning: Option<bool>,
/// Always use exit code 0, even when there are error-level diagnostics.
#[arg(long)]
pub(crate) exit_zero: bool,
/// Run in watch mode by re-running whenever files change.
#[arg(long, short = 'W')]
pub(crate) watch: bool,
}
impl CheckCommand {
pub(crate) fn into_options(self) -> Options {
let rules = if self.rules.is_empty() {
None
} else {
Some(
self.rules
.into_iter()
.map(|(rule, level)| (RangedValue::cli(rule), RangedValue::cli(level)))
.collect(),
)
};
Options {
environment: Some(EnvironmentOptions {
python_version: self
.python_version
.map(|version| RangedValue::cli(version.into())),
venv_path: self.venv_path.map(RelativePathBuf::cli),
typeshed: self.typeshed.map(RelativePathBuf::cli),
extra_paths: self.extra_search_path.map(|extra_search_paths| {
extra_search_paths
.into_iter()
.map(RelativePathBuf::cli)
.collect()
}),
..EnvironmentOptions::default()
}),
terminal: Some(TerminalOptions {
error_on_warning: self.error_on_warning,
}),
rules,
..Default::default()
}
}
}
/// A list of rules to enable or disable with a given severity.
///
/// This type is used to parse the `--error`, `--warn`, and `--ignore` arguments
/// while preserving the order in which they were specified (arguments last override previous severities).
#[derive(Debug)]
pub(crate) struct RulesArg(Vec<(String, lint::Level)>);
impl RulesArg {
fn is_empty(&self) -> bool {
self.0.is_empty()
}
fn into_iter(self) -> impl Iterator<Item = (String, lint::Level)> {
self.0.into_iter()
}
}
impl clap::FromArgMatches for RulesArg {
fn from_arg_matches(matches: &ArgMatches) -> Result<Self, Error> {
let mut rules = Vec::new();
for (level, arg_id) in [
(lint::Level::Ignore, "ignore"),
(lint::Level::Warn, "warn"),
(lint::Level::Error, "error"),
] {
let indices = matches.indices_of(arg_id).into_iter().flatten();
let levels = matches.get_many::<String>(arg_id).into_iter().flatten();
rules.extend(
indices
.zip(levels)
.map(|(index, rule)| (index, rule, level)),
);
}
// Sort by their index so that values specified later override earlier ones.
rules.sort_by_key(|(index, _, _)| *index);
Ok(Self(
rules
.into_iter()
.map(|(_, rule, level)| (rule.to_owned(), level))
.collect(),
))
}
fn update_from_arg_matches(&mut self, matches: &ArgMatches) -> Result<(), Error> {
self.0 = Self::from_arg_matches(matches)?.0;
Ok(())
}
}
impl clap::Args for RulesArg {
fn augment_args(cmd: clap::Command) -> clap::Command {
const HELP_HEADING: &str = "Enabling / disabling rules";
cmd.arg(
clap::Arg::new("error")
.long("error")
.action(ArgAction::Append)
.help("Treat the given rule as having severity 'error'. Can be specified multiple times.")
.value_name("RULE")
.help_heading(HELP_HEADING),
)
.arg(
clap::Arg::new("warn")
.long("warn")
.action(ArgAction::Append)
.help("Treat the given rule as having severity 'warn'. Can be specified multiple times.")
.value_name("RULE")
.help_heading(HELP_HEADING),
)
.arg(
clap::Arg::new("ignore")
.long("ignore")
.action(ArgAction::Append)
.help("Disables the rule. Can be specified multiple times.")
.value_name("RULE")
.help_heading(HELP_HEADING),
)
}
fn augment_args_for_update(cmd: clap::Command) -> clap::Command {
Self::augment_args(cmd)
}
}

View File

@@ -1,109 +1,28 @@
use std::io::{self, BufWriter, Write};
use std::process::{ExitCode, Termination};
use anyhow::Result;
use std::sync::Mutex;
use crate::args::{Args, CheckCommand, Command};
use crate::logging::setup_tracing;
use anyhow::{anyhow, Context};
use clap::Parser;
use colored::Colorize;
use crossbeam::channel as crossbeam_channel;
use python_version::PythonVersion;
use red_knot_python_semantic::SitePackages;
use red_knot_project::metadata::options::Options;
use red_knot_project::watch::ProjectWatcher;
use red_knot_project::{watch, Db};
use red_knot_project::{ProjectDatabase, ProjectMetadata};
use red_knot_server::run_server;
use red_knot_workspace::db::ProjectDatabase;
use red_knot_workspace::project::settings::Configuration;
use red_knot_workspace::project::ProjectMetadata;
use red_knot_workspace::watch;
use red_knot_workspace::watch::ProjectWatcher;
use ruff_db::diagnostic::Diagnostic;
use ruff_db::diagnostic::{Diagnostic, DisplayDiagnosticConfig, Severity};
use ruff_db::system::{OsSystem, System, SystemPath, SystemPathBuf};
use salsa::plumbing::ZalsaDatabase;
use crate::logging::{setup_tracing, Verbosity};
mod args;
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_configuration(&self, cli_cwd: &SystemPath) -> Configuration {
let mut configuration = Configuration::default();
if let Some(python_version) = self.python_version {
configuration.python_version = Some(python_version.into());
}
if let Some(venv_path) = &self.venv_path {
configuration.search_paths.site_packages = Some(SitePackages::Derived {
venv_path: SystemPath::absolute(venv_path, cli_cwd),
});
}
if let Some(typeshed) = &self.typeshed {
configuration.search_paths.typeshed = Some(SystemPath::absolute(typeshed, cli_cwd));
}
if let Some(extra_search_paths) = &self.extra_search_path {
configuration.search_paths.extra_paths = extra_search_paths
.iter()
.map(|path| Some(SystemPath::absolute(path, cli_cwd)))
.collect();
}
configuration
}
}
#[derive(Debug, clap::Subcommand)]
pub enum Command {
/// Start the language server
Server,
}
mod version;
#[allow(clippy::print_stdout, clippy::unnecessary_wraps, clippy::print_stderr)]
pub fn main() -> ExitStatus {
@@ -130,10 +49,21 @@ pub fn main() -> ExitStatus {
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);
match args.command {
Command::Server => run_server().map(|()| ExitStatus::Success),
Command::Check(check_args) => run_check(check_args),
Command::Version => version().map(|()| ExitStatus::Success),
}
}
pub(crate) fn version() -> Result<()> {
let mut stdout = BufWriter::new(io::stdout().lock());
let version_info = crate::version::version();
writeln!(stdout, "red knot {}", &version_info)?;
Ok(())
}
fn run_check(args: CheckCommand) -> anyhow::Result<ExitStatus> {
let verbosity = args.verbosity.level();
countme::enable(verbosity.is_trace());
let _guard = setup_tracing(verbosity)?;
@@ -163,19 +93,18 @@ fn run() -> anyhow::Result<ExitStatus> {
.transpose()?
.unwrap_or_else(|| cli_base_path.clone());
let system = OsSystem::new(cwd.clone());
let cli_configuration = args.to_configuration(&cwd);
let workspace_metadata = ProjectMetadata::discover(
system.current_directory(),
&system,
Some(&cli_configuration),
)?;
let system = OsSystem::new(cwd);
let watch = args.watch;
let exit_zero = args.exit_zero;
// TODO: Use the `program_settings` to compute the key for the database's persistent
// cache and load the cache if it exists.
let mut db = ProjectDatabase::new(workspace_metadata, system)?;
let cli_options = args.into_options();
let mut project_metadata = ProjectMetadata::discover(system.current_directory(), &system)?;
project_metadata.apply_cli_options(cli_options.clone());
project_metadata.apply_configuration_files(&system)?;
let (main_loop, main_loop_cancellation_token) = MainLoop::new(cli_configuration);
let mut db = ProjectDatabase::new(project_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));
@@ -187,7 +116,7 @@ fn run() -> anyhow::Result<ExitStatus> {
}
})?;
let exit_status = if args.watch {
let exit_status = if watch {
main_loop.watch(&mut db)?
} else {
main_loop.run(&mut db)
@@ -197,7 +126,11 @@ fn run() -> anyhow::Result<ExitStatus> {
std::mem::forget(db);
Ok(exit_status)
if exit_zero {
Ok(ExitStatus::Success)
} else {
Ok(exit_status)
}
}
#[derive(Copy, Clone)]
@@ -228,11 +161,11 @@ struct MainLoop {
/// The file system watcher, if running in watch mode.
watcher: Option<ProjectWatcher>,
cli_configuration: Configuration,
cli_options: Options,
}
impl MainLoop {
fn new(cli_configuration: Configuration) -> (Self, MainLoopCancellationToken) {
fn new(cli_options: Options) -> (Self, MainLoopCancellationToken) {
let (sender, receiver) = crossbeam_channel::bounded(10);
(
@@ -240,7 +173,7 @@ impl MainLoop {
sender: sender.clone(),
receiver,
watcher: None,
cli_configuration,
cli_options,
},
MainLoopCancellationToken { sender },
)
@@ -298,11 +231,24 @@ impl MainLoop {
result,
revision: check_revision,
} => {
let has_diagnostics = !result.is_empty();
let display_config = DisplayDiagnosticConfig::default()
.color(colored::control::SHOULD_COLORIZE.should_colorize());
let min_error_severity =
if db.project().settings(db).terminal().error_on_warning {
Severity::Warning
} else {
Severity::Error
};
let failed = result
.iter()
.any(|diagnostic| diagnostic.severity() >= min_error_severity);
if check_revision == revision {
#[allow(clippy::print_stdout)]
for diagnostic in result {
println!("{}", diagnostic.display(db));
println!("{}", diagnostic.display(db, &display_config));
}
} else {
tracing::debug!(
@@ -311,7 +257,7 @@ impl MainLoop {
}
if self.watcher.is_none() {
return if has_diagnostics {
return if failed {
ExitStatus::Failure
} else {
ExitStatus::Success
@@ -324,7 +270,7 @@ impl MainLoop {
MainLoopMessage::ApplyChanges(changes) => {
revision += 1;
// Automatically cancels any pending queries and waits for them to complete.
db.apply_changes(changes, Some(&self.cli_configuration));
db.apply_changes(changes, Some(&self.cli_options));
if let Some(watcher) = self.watcher.as_mut() {
watcher.update(db);
}

View File

@@ -40,7 +40,7 @@ impl std::fmt::Display for PythonVersion {
}
}
impl From<PythonVersion> for red_knot_python_semantic::PythonVersion {
impl From<PythonVersion> for ruff_python_ast::PythonVersion {
fn from(value: PythonVersion) -> Self {
match value {
PythonVersion::Py37 => Self::PY37,
@@ -61,8 +61,8 @@ mod tests {
#[test]
fn same_default_as_python_version() {
assert_eq!(
red_knot_python_semantic::PythonVersion::from(PythonVersion::default()),
red_knot_python_semantic::PythonVersion::default()
ruff_python_ast::PythonVersion::from(PythonVersion::default()),
ruff_python_ast::PythonVersion::default()
);
}
}

View File

@@ -1 +0,0 @@

View File

@@ -0,0 +1,105 @@
//! Code for representing Red Knot's release version number.
use std::fmt;
/// Information about the git repository where Red Knot was built from.
pub(crate) struct CommitInfo {
short_commit_hash: String,
commit_date: String,
commits_since_last_tag: u32,
}
/// Red Knot's version.
pub(crate) struct VersionInfo {
/// Red Knot's version, such as "0.5.1"
version: String,
/// Information about the git commit we may have been built from.
///
/// `None` if not built from a git repo or if retrieval failed.
commit_info: Option<CommitInfo>,
}
impl fmt::Display for VersionInfo {
/// Formatted version information: `<version>[+<commits>] (<commit> <date>)`
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.version)?;
if let Some(ref ci) = self.commit_info {
if ci.commits_since_last_tag > 0 {
write!(f, "+{}", ci.commits_since_last_tag)?;
}
write!(f, " ({} {})", ci.short_commit_hash, ci.commit_date)?;
}
Ok(())
}
}
/// Returns information about Red Knot's version.
pub(crate) fn version() -> VersionInfo {
// Environment variables are only read at compile-time
macro_rules! option_env_str {
($name:expr) => {
option_env!($name).map(|s| s.to_string())
};
}
// This version is pulled from Cargo.toml and set by Cargo
let version = option_env_str!("CARGO_PKG_VERSION").unwrap();
// Commit info is pulled from git and set by `build.rs`
let commit_info =
option_env_str!("RED_KNOT_COMMIT_SHORT_HASH").map(|short_commit_hash| CommitInfo {
short_commit_hash,
commit_date: option_env_str!("RED_KNOT_COMMIT_DATE").unwrap(),
commits_since_last_tag: option_env_str!("RED_KNOT_LAST_TAG_DISTANCE")
.as_deref()
.map_or(0, |value| value.parse::<u32>().unwrap_or(0)),
});
VersionInfo {
version,
commit_info,
}
}
#[cfg(test)]
mod tests {
use insta::assert_snapshot;
use super::{CommitInfo, VersionInfo};
#[test]
fn version_formatting() {
let version = VersionInfo {
version: "0.0.0".to_string(),
commit_info: None,
};
assert_snapshot!(version, @"0.0.0");
}
#[test]
fn version_formatting_with_commit_info() {
let version = VersionInfo {
version: "0.0.0".to_string(),
commit_info: Some(CommitInfo {
short_commit_hash: "53b0f5d92".to_string(),
commit_date: "2023-10-19".to_string(),
commits_since_last_tag: 0,
}),
};
assert_snapshot!(version, @"0.0.0 (53b0f5d92 2023-10-19)");
}
#[test]
fn version_formatting_with_commits_since_last_tag() {
let version = VersionInfo {
version: "0.0.0".to_string(),
commit_info: Some(CommitInfo {
short_commit_hash: "53b0f5d92".to_string(),
commit_date: "2023-10-19".to_string(),
commits_since_last_tag: 24,
}),
};
assert_snapshot!(version, @"0.0.0+24 (53b0f5d92 2023-10-19)");
}
}

View File

@@ -0,0 +1,903 @@
use anyhow::Context;
use insta::internals::SettingsBindDropGuard;
use insta_cmd::{assert_cmd_snapshot, get_cargo_bin};
use std::path::{Path, PathBuf};
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 config_override() -> anyhow::Result<()> {
let case = TestCase::with_files([
(
"pyproject.toml",
r#"
[tool.knot.environment]
python-version = "3.11"
"#,
),
(
"test.py",
r#"
import sys
# Access `sys.last_exc` that was only added in Python 3.12
print(sys.last_exc)
"#,
),
])?;
assert_cmd_snapshot!(case.command(), @r###"
success: false
exit_code: 1
----- stdout -----
error: lint:unresolved-attribute
--> <temp_dir>/test.py:5:7
|
4 | # Access `sys.last_exc` that was only added in Python 3.12
5 | print(sys.last_exc)
| ^^^^^^^^^^^^ Type `<module 'sys'>` has no attribute `last_exc`
|
----- stderr -----
"###);
assert_cmd_snapshot!(case.command().arg("--python-version").arg("3.12"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
");
Ok(())
}
/// Paths specified on the CLI are relative to the current working directory and not the project root.
///
/// We test this by adding an extra search path from the CLI to the libs directory when
/// running the CLI from the child directory (using relative paths).
///
/// Project layout:
/// ```
/// - libs
/// |- utils.py
/// - child
/// | - test.py
/// - pyproject.toml
/// ```
///
/// And the command is run in the `child` directory.
#[test]
fn cli_arguments_are_relative_to_the_current_directory() -> anyhow::Result<()> {
let case = TestCase::with_files([
(
"pyproject.toml",
r#"
[tool.knot.environment]
python-version = "3.11"
"#,
),
(
"libs/utils.py",
r#"
def add(a: int, b: int) -> int:
a + b
"#,
),
(
"child/test.py",
r#"
from utils import add
stat = add(10, 15)
"#,
),
])?;
// Make sure that the CLI fails when the `libs` directory is not in the search path.
assert_cmd_snapshot!(case.command().current_dir(case.root().join("child")), @r###"
success: false
exit_code: 1
----- stdout -----
error: lint:unresolved-import
--> <temp_dir>/child/test.py:2:6
|
2 | from utils import add
| ^^^^^ Cannot resolve import `utils`
3 |
4 | stat = add(10, 15)
|
----- stderr -----
"###);
assert_cmd_snapshot!(case.command().current_dir(case.root().join("child")).arg("--extra-search-path").arg("../libs"), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
");
Ok(())
}
/// Paths specified in a configuration file are relative to the project root.
///
/// We test this by adding `libs` (as a relative path) to the extra search path in the configuration and run
/// the CLI from a subdirectory.
///
/// Project layout:
/// ```
/// - libs
/// |- utils.py
/// - child
/// | - test.py
/// - pyproject.toml
/// ```
#[test]
fn paths_in_configuration_files_are_relative_to_the_project_root() -> anyhow::Result<()> {
let case = TestCase::with_files([
(
"pyproject.toml",
r#"
[tool.knot.environment]
python-version = "3.11"
extra-paths = ["libs"]
"#,
),
(
"libs/utils.py",
r#"
def add(a: int, b: int) -> int:
a + b
"#,
),
(
"child/test.py",
r#"
from utils import add
stat = add(10, 15)
"#,
),
])?;
assert_cmd_snapshot!(case.command().current_dir(case.root().join("child")), @r"
success: true
exit_code: 0
----- stdout -----
----- stderr -----
");
Ok(())
}
/// The rule severity can be changed in the configuration file
#[test]
fn configuration_rule_severity() -> anyhow::Result<()> {
let case = TestCase::with_file(
"test.py",
r#"
y = 4 / 0
for a in range(0, y):
x = a
print(x) # possibly-unresolved-reference
"#,
)?;
// Assert that there's a possibly unresolved reference diagnostic
// and that division-by-zero has a severity of error by default.
assert_cmd_snapshot!(case.command(), @r###"
success: false
exit_code: 1
----- stdout -----
error: lint:division-by-zero
--> <temp_dir>/test.py:2:5
|
2 | y = 4 / 0
| ^^^^^ Cannot divide object of type `Literal[4]` by zero
3 |
4 | for a in range(0, y):
|
warning: lint:possibly-unresolved-reference
--> <temp_dir>/test.py:7:7
|
5 | x = a
6 |
7 | print(x) # possibly-unresolved-reference
| - Name `x` used when possibly not defined
|
----- stderr -----
"###);
case.write_file(
"pyproject.toml",
r#"
[tool.knot.rules]
division-by-zero = "warn" # demote to warn
possibly-unresolved-reference = "ignore"
"#,
)?;
assert_cmd_snapshot!(case.command(), @r###"
success: true
exit_code: 0
----- stdout -----
warning: lint:division-by-zero
--> <temp_dir>/test.py:2:5
|
2 | y = 4 / 0
| ----- Cannot divide object of type `Literal[4]` by zero
3 |
4 | for a in range(0, y):
|
----- stderr -----
"###);
Ok(())
}
/// The rule severity can be changed using `--ignore`, `--warn`, and `--error`
#[test]
fn cli_rule_severity() -> anyhow::Result<()> {
let case = TestCase::with_file(
"test.py",
r#"
import does_not_exit
y = 4 / 0
for a in range(0, y):
x = a
print(x) # possibly-unresolved-reference
"#,
)?;
// Assert that there's a possibly unresolved reference diagnostic
// and that division-by-zero has a severity of error by default.
assert_cmd_snapshot!(case.command(), @r###"
success: false
exit_code: 1
----- stdout -----
error: lint:unresolved-import
--> <temp_dir>/test.py:2:8
|
2 | import does_not_exit
| ^^^^^^^^^^^^^ Cannot resolve import `does_not_exit`
3 |
4 | y = 4 / 0
|
error: lint:division-by-zero
--> <temp_dir>/test.py:4:5
|
2 | import does_not_exit
3 |
4 | y = 4 / 0
| ^^^^^ Cannot divide object of type `Literal[4]` by zero
5 |
6 | for a in range(0, y):
|
warning: lint:possibly-unresolved-reference
--> <temp_dir>/test.py:9:7
|
7 | x = a
8 |
9 | print(x) # possibly-unresolved-reference
| - Name `x` used when possibly not defined
|
----- stderr -----
"###);
assert_cmd_snapshot!(
case
.command()
.arg("--ignore")
.arg("possibly-unresolved-reference")
.arg("--warn")
.arg("division-by-zero")
.arg("--warn")
.arg("unresolved-import"),
@r###"
success: true
exit_code: 0
----- stdout -----
warning: lint:unresolved-import
--> <temp_dir>/test.py:2:8
|
2 | import does_not_exit
| ------------- Cannot resolve import `does_not_exit`
3 |
4 | y = 4 / 0
|
warning: lint:division-by-zero
--> <temp_dir>/test.py:4:5
|
2 | import does_not_exit
3 |
4 | y = 4 / 0
| ----- Cannot divide object of type `Literal[4]` by zero
5 |
6 | for a in range(0, y):
|
----- stderr -----
"###
);
Ok(())
}
/// The rule severity can be changed using `--ignore`, `--warn`, and `--error` and
/// values specified last override previous severities.
#[test]
fn cli_rule_severity_precedence() -> anyhow::Result<()> {
let case = TestCase::with_file(
"test.py",
r#"
y = 4 / 0
for a in range(0, y):
x = a
print(x) # possibly-unresolved-reference
"#,
)?;
// Assert that there's a possibly unresolved reference diagnostic
// and that division-by-zero has a severity of error by default.
assert_cmd_snapshot!(case.command(), @r###"
success: false
exit_code: 1
----- stdout -----
error: lint:division-by-zero
--> <temp_dir>/test.py:2:5
|
2 | y = 4 / 0
| ^^^^^ Cannot divide object of type `Literal[4]` by zero
3 |
4 | for a in range(0, y):
|
warning: lint:possibly-unresolved-reference
--> <temp_dir>/test.py:7:7
|
5 | x = a
6 |
7 | print(x) # possibly-unresolved-reference
| - Name `x` used when possibly not defined
|
----- stderr -----
"###);
assert_cmd_snapshot!(
case
.command()
.arg("--error")
.arg("possibly-unresolved-reference")
.arg("--warn")
.arg("division-by-zero")
// Override the error severity with warning
.arg("--ignore")
.arg("possibly-unresolved-reference"),
@r###"
success: true
exit_code: 0
----- stdout -----
warning: lint:division-by-zero
--> <temp_dir>/test.py:2:5
|
2 | y = 4 / 0
| ----- Cannot divide object of type `Literal[4]` by zero
3 |
4 | for a in range(0, y):
|
----- stderr -----
"###
);
Ok(())
}
/// Red Knot warns about unknown rules specified in a configuration file
#[test]
fn configuration_unknown_rules() -> anyhow::Result<()> {
let case = TestCase::with_files([
(
"pyproject.toml",
r#"
[tool.knot.rules]
division-by-zer = "warn" # incorrect rule name
"#,
),
("test.py", "print(10)"),
])?;
assert_cmd_snapshot!(case.command(), @r###"
success: true
exit_code: 0
----- stdout -----
warning: unknown-rule
--> <temp_dir>/pyproject.toml:3:1
|
2 | [tool.knot.rules]
3 | division-by-zer = "warn" # incorrect rule name
| --------------- Unknown lint rule `division-by-zer`
|
----- stderr -----
"###);
Ok(())
}
/// Red Knot warns about unknown rules specified in a CLI argument
#[test]
fn cli_unknown_rules() -> anyhow::Result<()> {
let case = TestCase::with_file("test.py", "print(10)")?;
assert_cmd_snapshot!(case.command().arg("--ignore").arg("division-by-zer"), @r###"
success: true
exit_code: 0
----- stdout -----
warning: unknown-rule: Unknown lint rule `division-by-zer`
----- stderr -----
"###);
Ok(())
}
#[test]
fn exit_code_only_warnings() -> anyhow::Result<()> {
let case = TestCase::with_file("test.py", r"print(x) # [unresolved-reference]")?;
assert_cmd_snapshot!(case.command(), @r###"
success: true
exit_code: 0
----- stdout -----
warning: lint:unresolved-reference
--> <temp_dir>/test.py:1:7
|
1 | print(x) # [unresolved-reference]
| - Name `x` used when not defined
|
----- stderr -----
"###);
Ok(())
}
#[test]
fn exit_code_only_info() -> anyhow::Result<()> {
let case = TestCase::with_file(
"test.py",
r#"
from typing_extensions import reveal_type
reveal_type(1)
"#,
)?;
assert_cmd_snapshot!(case.command(), @r###"
success: true
exit_code: 0
----- stdout -----
info: revealed-type
--> <temp_dir>/test.py:3:1
|
2 | from typing_extensions import reveal_type
3 | reveal_type(1)
| -------------- info: Revealed type is `Literal[1]`
|
----- stderr -----
"###);
Ok(())
}
#[test]
fn exit_code_only_info_and_error_on_warning_is_true() -> anyhow::Result<()> {
let case = TestCase::with_file(
"test.py",
r#"
from typing_extensions import reveal_type
reveal_type(1)
"#,
)?;
assert_cmd_snapshot!(case.command().arg("--error-on-warning"), @r###"
success: true
exit_code: 0
----- stdout -----
info: revealed-type
--> <temp_dir>/test.py:3:1
|
2 | from typing_extensions import reveal_type
3 | reveal_type(1)
| -------------- info: Revealed type is `Literal[1]`
|
----- stderr -----
"###);
Ok(())
}
#[test]
fn exit_code_no_errors_but_error_on_warning_is_true() -> anyhow::Result<()> {
let case = TestCase::with_file("test.py", r"print(x) # [unresolved-reference]")?;
assert_cmd_snapshot!(case.command().arg("--error-on-warning"), @r###"
success: false
exit_code: 1
----- stdout -----
warning: lint:unresolved-reference
--> <temp_dir>/test.py:1:7
|
1 | print(x) # [unresolved-reference]
| - Name `x` used when not defined
|
----- stderr -----
"###);
Ok(())
}
#[test]
fn exit_code_no_errors_but_error_on_warning_is_enabled_in_configuration() -> anyhow::Result<()> {
let case = TestCase::with_files([
("test.py", r"print(x) # [unresolved-reference]"),
(
"knot.toml",
r#"
[terminal]
error-on-warning = true
"#,
),
])?;
assert_cmd_snapshot!(case.command(), @r###"
success: false
exit_code: 1
----- stdout -----
warning: lint:unresolved-reference
--> <temp_dir>/test.py:1:7
|
1 | print(x) # [unresolved-reference]
| - Name `x` used when not defined
|
----- stderr -----
"###);
Ok(())
}
#[test]
fn exit_code_both_warnings_and_errors() -> anyhow::Result<()> {
let case = TestCase::with_file(
"test.py",
r#"
print(x) # [unresolved-reference]
print(4[1]) # [non-subscriptable]
"#,
)?;
assert_cmd_snapshot!(case.command(), @r###"
success: false
exit_code: 1
----- stdout -----
warning: lint:unresolved-reference
--> <temp_dir>/test.py:2:7
|
2 | print(x) # [unresolved-reference]
| - Name `x` used when not defined
3 | print(4[1]) # [non-subscriptable]
|
error: lint:non-subscriptable
--> <temp_dir>/test.py:3:7
|
2 | print(x) # [unresolved-reference]
3 | print(4[1]) # [non-subscriptable]
| ^ Cannot subscript object of type `Literal[4]` with no `__getitem__` method
|
----- stderr -----
"###);
Ok(())
}
#[test]
fn exit_code_both_warnings_and_errors_and_error_on_warning_is_true() -> anyhow::Result<()> {
let case = TestCase::with_file(
"test.py",
r###"
print(x) # [unresolved-reference]
print(4[1]) # [non-subscriptable]
"###,
)?;
assert_cmd_snapshot!(case.command().arg("--error-on-warning"), @r###"
success: false
exit_code: 1
----- stdout -----
warning: lint:unresolved-reference
--> <temp_dir>/test.py:2:7
|
2 | print(x) # [unresolved-reference]
| - Name `x` used when not defined
3 | print(4[1]) # [non-subscriptable]
|
error: lint:non-subscriptable
--> <temp_dir>/test.py:3:7
|
2 | print(x) # [unresolved-reference]
3 | print(4[1]) # [non-subscriptable]
| ^ Cannot subscript object of type `Literal[4]` with no `__getitem__` method
|
----- stderr -----
"###);
Ok(())
}
#[test]
fn exit_code_exit_zero_is_true() -> anyhow::Result<()> {
let case = TestCase::with_file(
"test.py",
r#"
print(x) # [unresolved-reference]
print(4[1]) # [non-subscriptable]
"#,
)?;
assert_cmd_snapshot!(case.command().arg("--exit-zero"), @r###"
success: true
exit_code: 0
----- stdout -----
warning: lint:unresolved-reference
--> <temp_dir>/test.py:2:7
|
2 | print(x) # [unresolved-reference]
| - Name `x` used when not defined
3 | print(4[1]) # [non-subscriptable]
|
error: lint:non-subscriptable
--> <temp_dir>/test.py:3:7
|
2 | print(x) # [unresolved-reference]
3 | print(4[1]) # [non-subscriptable]
| ^ Cannot subscript object of type `Literal[4]` with no `__getitem__` method
|
----- stderr -----
"###);
Ok(())
}
#[test]
fn user_configuration() -> anyhow::Result<()> {
let case = TestCase::with_files([
(
"project/knot.toml",
r#"
[rules]
division-by-zero = "warn"
"#,
),
(
"project/main.py",
r#"
y = 4 / 0
for a in range(0, y):
x = a
print(x)
"#,
),
])?;
let config_directory = case.root().join("home/.config");
let config_env_var = if cfg!(windows) {
"APPDATA"
} else {
"XDG_CONFIG_HOME"
};
assert_cmd_snapshot!(
case.command().current_dir(case.root().join("project")).env(config_env_var, config_directory.as_os_str()),
@r###"
success: true
exit_code: 0
----- stdout -----
warning: lint:division-by-zero
--> <temp_dir>/project/main.py:2:5
|
2 | y = 4 / 0
| ----- Cannot divide object of type `Literal[4]` by zero
3 |
4 | for a in range(0, y):
|
warning: lint:possibly-unresolved-reference
--> <temp_dir>/project/main.py:7:7
|
5 | x = a
6 |
7 | print(x)
| - Name `x` used when possibly not defined
|
----- stderr -----
"###
);
// The user-level configuration promotes `possibly-unresolved-reference` to an error.
// Changing the level for `division-by-zero` has no effect, because the project-level configuration
// has higher precedence.
case.write_file(
config_directory.join("knot/knot.toml"),
r#"
[rules]
division-by-zero = "error"
possibly-unresolved-reference = "error"
"#,
)?;
assert_cmd_snapshot!(
case.command().current_dir(case.root().join("project")).env(config_env_var, config_directory.as_os_str()),
@r###"
success: false
exit_code: 1
----- stdout -----
warning: lint:division-by-zero
--> <temp_dir>/project/main.py:2:5
|
2 | y = 4 / 0
| ----- Cannot divide object of type `Literal[4]` by zero
3 |
4 | for a in range(0, y):
|
error: lint:possibly-unresolved-reference
--> <temp_dir>/project/main.py:7:7
|
5 | x = a
6 |
7 | print(x)
| ^ Name `x` used when possibly not defined
|
----- stderr -----
"###
);
Ok(())
}
struct TestCase {
_temp_dir: TempDir,
_settings_scope: SettingsBindDropGuard,
project_dir: PathBuf,
}
impl TestCase {
fn new() -> anyhow::Result<Self> {
let temp_dir = TempDir::new()?;
// Canonicalize the tempdir path because macos uses symlinks for tempdirs
// and that doesn't play well with our snapshot filtering.
let project_dir = temp_dir
.path()
.canonicalize()
.context("Failed to canonicalize project path")?;
let mut settings = insta::Settings::clone_current();
settings.add_filter(&tempdir_filter(&project_dir), "<temp_dir>/");
settings.add_filter(r#"\\(\w\w|\s|\.|")"#, "/$1");
let settings_scope = settings.bind_to_scope();
Ok(Self {
project_dir,
_temp_dir: temp_dir,
_settings_scope: settings_scope,
})
}
fn with_files<'a>(files: impl IntoIterator<Item = (&'a str, &'a str)>) -> anyhow::Result<Self> {
let case = Self::new()?;
case.write_files(files)?;
Ok(case)
}
fn with_file(path: impl AsRef<Path>, content: &str) -> anyhow::Result<Self> {
let case = Self::new()?;
case.write_file(path, content)?;
Ok(case)
}
fn write_files<'a>(
&self,
files: impl IntoIterator<Item = (&'a str, &'a str)>,
) -> anyhow::Result<()> {
for (path, content) in files {
self.write_file(path, content)?;
}
Ok(())
}
fn write_file(&self, path: impl AsRef<Path>, content: &str) -> anyhow::Result<()> {
let path = path.as_ref();
let path = self.project_dir.join(path);
if let Some(parent) = path.parent() {
std::fs::create_dir_all(parent)
.with_context(|| format!("Failed to create directory `{}`", parent.display()))?;
}
std::fs::write(&path, &*ruff_python_trivia::textwrap::dedent(content))
.with_context(|| format!("Failed to write file `{path}`", path = path.display()))?;
Ok(())
}
fn root(&self) -> &Path {
&self.project_dir
}
fn command(&self) -> Command {
let mut command = Command::new(get_cargo_bin("red_knot"));
command.current_dir(&self.project_dir).arg("check");
command
}
}
fn tempdir_filter(path: &Path) -> String {
format!(r"{}\\?/?", regex::escape(path.to_str().unwrap()))
}

View File

@@ -4,15 +4,19 @@ use std::io::Write;
use std::time::{Duration, Instant};
use anyhow::{anyhow, Context};
use red_knot_python_semantic::{resolve_module, ModuleName, Program, PythonVersion, SitePackages};
use red_knot_workspace::db::{Db, ProjectDatabase};
use red_knot_workspace::project::settings::{Configuration, SearchPathConfiguration};
use red_knot_workspace::project::ProjectMetadata;
use red_knot_workspace::watch::{directory_watcher, ChangeEvent, ProjectWatcher};
use red_knot_project::metadata::options::{EnvironmentOptions, Options};
use red_knot_project::metadata::pyproject::{PyProject, Tool};
use red_knot_project::metadata::value::{RangedValue, RelativePathBuf};
use red_knot_project::watch::{directory_watcher, ChangeEvent, ProjectWatcher};
use red_knot_project::{Db, ProjectDatabase, ProjectMetadata};
use red_knot_python_semantic::{resolve_module, ModuleName, PythonPlatform};
use ruff_db::files::{system_path_to_file, File, FileError};
use ruff_db::source::source_text;
use ruff_db::system::{OsSystem, SystemPath, SystemPathBuf};
use ruff_db::system::{
OsSystem, System, SystemPath, SystemPathBuf, UserConfigDirectoryOverrideGuard,
};
use ruff_db::Upcast;
use ruff_python_ast::PythonVersion;
struct TestCase {
db: ProjectDatabase,
@@ -22,7 +26,6 @@ struct TestCase {
/// We need to hold on to it in the test case or the temp files get deleted.
_temp_dir: tempfile::TempDir,
root_dir: SystemPathBuf,
configuration: Configuration,
}
impl TestCase {
@@ -47,7 +50,7 @@ impl TestCase {
#[track_caller]
fn panic_with_formatted_events(events: Vec<ChangeEvent>) -> Vec<ChangeEvent> {
panic!(
"Didn't observe expected change:\n{}",
"Didn't observe the expected event. The following events occurred:\n{}",
events
.into_iter()
.map(|event| format!(" - {event:?}"))
@@ -112,19 +115,44 @@ impl TestCase {
Ok(all_events)
}
fn take_watch_changes(&self) -> Vec<ChangeEvent> {
self.try_take_watch_changes(Duration::from_secs(10))
fn take_watch_changes<M: MatchEvent>(&self, matcher: M) -> Vec<ChangeEvent> {
self.try_take_watch_changes(matcher, Duration::from_secs(10))
.expect("Expected watch changes but observed none")
}
fn try_take_watch_changes(&self, timeout: Duration) -> Option<Vec<ChangeEvent>> {
let watcher = self.watcher.as_ref()?;
fn try_take_watch_changes<M: MatchEvent>(
&self,
mut matcher: M,
timeout: Duration,
) -> Result<Vec<ChangeEvent>, Vec<ChangeEvent>> {
let watcher = self
.watcher
.as_ref()
.expect("Cannot call `try_take_watch_changes` after `stop_watch`");
let mut all_events = self
.changes_receiver
.recv_timeout(timeout)
.unwrap_or_default();
watcher.flush();
let start = Instant::now();
let mut all_events = Vec::new();
loop {
let events = self
.changes_receiver
.recv_timeout(Duration::from_millis(100))
.unwrap_or_default();
if events
.iter()
.any(|event| matcher.match_event(event) || event.is_rescan())
{
all_events.extend(events);
break;
}
all_events.extend(events);
if start.elapsed() > timeout {
return Err(all_events);
}
}
while let Ok(event) = self
.changes_receiver
@@ -134,26 +162,28 @@ impl TestCase {
watcher.flush();
}
if all_events.is_empty() {
return None;
}
Some(all_events)
Ok(all_events)
}
fn apply_changes(&mut self, changes: Vec<ChangeEvent>) {
self.db.apply_changes(changes, Some(&self.configuration));
self.db.apply_changes(changes, None);
}
fn update_search_path_settings(
&mut self,
configuration: SearchPathConfiguration,
) -> anyhow::Result<()> {
let program = Program::get(self.db());
fn update_options(&mut self, options: Options) -> anyhow::Result<()> {
std::fs::write(
self.project_path("pyproject.toml").as_std_path(),
toml::to_string(&PyProject {
project: None,
tool: Some(Tool {
knot: Some(options),
}),
})
.context("Failed to serialize options")?,
)
.context("Failed to write configuration")?;
let new_settings = configuration.to_settings(self.db.project().root(&self.db));
self.configuration.search_paths = configuration;
program.update_search_paths(&mut self.db, &new_settings)?;
let changes = self.take_watch_changes(event_for_file("pyproject.toml"));
self.apply_changes(changes);
if let Some(watcher) = &mut self.watcher {
watcher.update(&self.db);
@@ -193,17 +223,44 @@ where
}
trait SetupFiles {
fn setup(self, root_path: &SystemPath, project_path: &SystemPath) -> anyhow::Result<()>;
fn setup(self, context: &SetupContext) -> anyhow::Result<()>;
}
struct SetupContext<'a> {
system: &'a OsSystem,
root_path: &'a SystemPath,
}
impl<'a> SetupContext<'a> {
fn system(&self) -> &'a OsSystem {
self.system
}
fn join_project_path(&self, relative: impl AsRef<SystemPath>) -> SystemPathBuf {
self.project_path().join(relative)
}
fn project_path(&self) -> &SystemPath {
self.system.current_directory()
}
fn root_path(&self) -> &'a SystemPath {
self.root_path
}
fn join_root_path(&self, relative: impl AsRef<SystemPath>) -> SystemPathBuf {
self.root_path().join(relative)
}
}
impl<const N: usize, P> SetupFiles for [(P, &'static str); N]
where
P: AsRef<SystemPath>,
{
fn setup(self, _root_path: &SystemPath, project_path: &SystemPath) -> anyhow::Result<()> {
fn setup(self, context: &SetupContext) -> anyhow::Result<()> {
for (relative_path, content) in self {
let relative_path = relative_path.as_ref();
let absolute_path = project_path.join(relative_path);
let absolute_path = context.join_project_path(relative_path);
if let Some(parent) = absolute_path.parent() {
std::fs::create_dir_all(parent).with_context(|| {
format!("Failed to create parent directory for file `{relative_path}`")
@@ -223,10 +280,10 @@ where
impl<F> SetupFiles for F
where
F: FnOnce(&SystemPath, &SystemPath) -> anyhow::Result<()>,
F: FnOnce(&SetupContext) -> anyhow::Result<()>,
{
fn setup(self, root_path: &SystemPath, project_path: &SystemPath) -> anyhow::Result<()> {
self(root_path, project_path)
fn setup(self, context: &SetupContext) -> anyhow::Result<()> {
self(context)
}
}
@@ -234,14 +291,12 @@ fn setup<F>(setup_files: F) -> anyhow::Result<TestCase>
where
F: SetupFiles,
{
setup_with_search_paths(setup_files, |_root, _project_path| {
SearchPathConfiguration::default()
})
setup_with_options(setup_files, |_context| None)
}
fn setup_with_search_paths<F>(
fn setup_with_options<F>(
setup_files: F,
create_search_paths: impl FnOnce(&SystemPath, &SystemPath) -> SearchPathConfiguration,
create_options: impl FnOnce(&SetupContext) -> Option<Options>,
) -> anyhow::Result<TestCase>
where
F: SetupFiles,
@@ -269,38 +324,45 @@ where
std::fs::create_dir_all(project_path.as_std_path())
.with_context(|| format!("Failed to create project directory `{project_path}`"))?;
let system = OsSystem::new(&project_path);
let setup_context = SetupContext {
system: &system,
root_path: &root_path,
};
setup_files
.setup(&root_path, &project_path)
.setup(&setup_context)
.context("Failed to setup test files")?;
let system = OsSystem::new(&project_path);
if let Some(options) = create_options(&setup_context) {
std::fs::write(
project_path.join("pyproject.toml").as_std_path(),
toml::to_string(&PyProject {
project: None,
tool: Some(Tool {
knot: Some(options),
}),
})
.context("Failed to serialize options")?,
)
.context("Failed to write configuration")?;
}
let search_paths = create_search_paths(&root_path, &project_path);
let mut project = ProjectMetadata::discover(&project_path, &system)?;
project.apply_configuration_files(&system)?;
for path in search_paths
let program_settings = project.to_program_settings(&system);
for path in program_settings
.search_paths
.extra_paths
.iter()
.flatten()
.chain(search_paths.typeshed.iter())
.chain(search_paths.site_packages.iter().flat_map(|site_packages| {
if let SitePackages::Known(path) = site_packages {
path.as_slice()
} else {
&[]
}
}))
.chain(program_settings.search_paths.custom_typeshed.as_ref())
{
std::fs::create_dir_all(path.as_std_path())
.with_context(|| format!("Failed to create search path `{path}`"))?;
}
let configuration = Configuration {
python_version: Some(PythonVersion::PY312),
search_paths,
};
let project = ProjectMetadata::discover(&project_path, &system, Some(&configuration))?;
let db = ProjectDatabase::new(project, system)?;
let (sender, receiver) = crossbeam::channel::unbounded();
@@ -316,12 +378,12 @@ where
watcher: Some(watcher),
_temp_dir: temp_dir,
root_dir: root_path,
configuration,
};
// Sometimes the file watcher reports changes for events that happened before the watcher was started.
// Do a best effort at dropping these events.
test_case.try_take_watch_changes(Duration::from_millis(100));
let _ =
test_case.try_take_watch_changes(|_event: &ChangeEvent| true, Duration::from_millis(100));
Ok(test_case)
}
@@ -762,13 +824,17 @@ fn directory_deleted() -> anyhow::Result<()> {
#[test]
fn search_path() -> anyhow::Result<()> {
let mut case =
setup_with_search_paths([("bar.py", "import sub.a")], |root_path, _project_path| {
SearchPathConfiguration {
site_packages: Some(SitePackages::Known(vec![root_path.join("site_packages")])),
..SearchPathConfiguration::default()
}
})?;
let mut case = setup_with_options([("bar.py", "import sub.a")], |context| {
Some(Options {
environment: Some(EnvironmentOptions {
extra_paths: Some(vec![RelativePathBuf::cli(
context.join_root_path("site_packages"),
)]),
..EnvironmentOptions::default()
}),
..Options::default()
})
})?;
let site_packages = case.root_path().join("site_packages");
@@ -802,9 +868,12 @@ fn add_search_path() -> anyhow::Result<()> {
assert!(resolve_module(case.db().upcast(), &ModuleName::new_static("a").unwrap()).is_none());
// Register site-packages as a search path.
case.update_search_path_settings(SearchPathConfiguration {
site_packages: Some(SitePackages::Known(vec![site_packages.clone()])),
..SearchPathConfiguration::default()
case.update_options(Options {
environment: Some(EnvironmentOptions {
extra_paths: Some(vec![RelativePathBuf::cli("site_packages")]),
..EnvironmentOptions::default()
}),
..Options::default()
})
.expect("Search path settings to be valid");
@@ -821,19 +890,24 @@ fn add_search_path() -> anyhow::Result<()> {
#[test]
fn remove_search_path() -> anyhow::Result<()> {
let mut case =
setup_with_search_paths([("bar.py", "import sub.a")], |root_path, _project_path| {
SearchPathConfiguration {
site_packages: Some(SitePackages::Known(vec![root_path.join("site_packages")])),
..SearchPathConfiguration::default()
}
})?;
let mut case = setup_with_options([("bar.py", "import sub.a")], |context| {
Some(Options {
environment: Some(EnvironmentOptions {
extra_paths: Some(vec![RelativePathBuf::cli(
context.join_root_path("site_packages"),
)]),
..EnvironmentOptions::default()
}),
..Options::default()
})
})?;
// Remove site packages from the search path settings.
let site_packages = case.root_path().join("site_packages");
case.update_search_path_settings(SearchPathConfiguration {
site_packages: None,
..SearchPathConfiguration::default()
case.update_options(Options {
environment: None,
..Options::default()
})
.expect("Search path settings to be valid");
@@ -846,23 +920,96 @@ fn remove_search_path() -> anyhow::Result<()> {
Ok(())
}
#[test]
fn change_python_version_and_platform() -> anyhow::Result<()> {
let mut case = setup_with_options(
// `sys.last_exc` is a Python 3.12 only feature
// `os.getegid()` is Unix only
[(
"bar.py",
r#"
import sys
import os
print(sys.last_exc, os.getegid())
"#,
)],
|_context| {
Some(Options {
environment: Some(EnvironmentOptions {
python_version: Some(RangedValue::cli(PythonVersion::PY311)),
python_platform: Some(RangedValue::cli(PythonPlatform::Identifier(
"win32".to_string(),
))),
..EnvironmentOptions::default()
}),
..Options::default()
})
},
)?;
let diagnostics = case.db.check().context("Failed to check project.")?;
assert_eq!(diagnostics.len(), 2);
assert_eq!(
diagnostics[0].message(),
"Type `<module 'sys'>` has no attribute `last_exc`"
);
assert_eq!(
diagnostics[1].message(),
"Type `<module 'os'>` has no attribute `getegid`"
);
// Change the python version
case.update_options(Options {
environment: Some(EnvironmentOptions {
python_version: Some(RangedValue::cli(PythonVersion::PY312)),
python_platform: Some(RangedValue::cli(PythonPlatform::Identifier(
"linux".to_string(),
))),
..EnvironmentOptions::default()
}),
..Options::default()
})
.expect("Search path settings to be valid");
let diagnostics = case.db.check().context("Failed to check project.")?;
assert!(diagnostics.is_empty());
Ok(())
}
#[test]
fn changed_versions_file() -> anyhow::Result<()> {
let mut case = setup_with_search_paths(
|root_path: &SystemPath, project_path: &SystemPath| {
std::fs::write(project_path.join("bar.py").as_std_path(), "import sub.a")?;
std::fs::create_dir_all(root_path.join("typeshed/stdlib").as_std_path())?;
std::fs::write(root_path.join("typeshed/stdlib/VERSIONS").as_std_path(), "")?;
let mut case = setup_with_options(
|context: &SetupContext| {
std::fs::write(
root_path.join("typeshed/stdlib/os.pyi").as_std_path(),
context.join_project_path("bar.py").as_std_path(),
"import sub.a",
)?;
std::fs::create_dir_all(context.join_root_path("typeshed/stdlib").as_std_path())?;
std::fs::write(
context
.join_root_path("typeshed/stdlib/VERSIONS")
.as_std_path(),
"",
)?;
std::fs::write(
context
.join_root_path("typeshed/stdlib/os.pyi")
.as_std_path(),
"# not important",
)?;
Ok(())
},
|root_path, _project_path| SearchPathConfiguration {
typeshed: Some(root_path.join("typeshed")),
..SearchPathConfiguration::default()
|context| {
Some(Options {
environment: Some(EnvironmentOptions {
typeshed: Some(RelativePathBuf::cli(context.join_root_path("typeshed"))),
..EnvironmentOptions::default()
}),
..Options::default()
})
},
)?;
@@ -909,12 +1056,12 @@ fn changed_versions_file() -> anyhow::Result<()> {
/// we're seeing is that Windows only emits a single event, similar to Linux.
#[test]
fn hard_links_in_project() -> anyhow::Result<()> {
let mut case = setup(|_root: &SystemPath, project: &SystemPath| {
let foo_path = project.join("foo.py");
let mut case = setup(|context: &SetupContext| {
let foo_path = context.join_project_path("foo.py");
std::fs::write(foo_path.as_std_path(), "print('Version 1')")?;
// Create a hardlink to `foo`
let bar_path = project.join("bar.py");
let bar_path = context.join_project_path("bar.py");
std::fs::hard_link(foo_path.as_std_path(), bar_path.as_std_path())
.context("Failed to create hard link from foo.py -> bar.py")?;
@@ -980,12 +1127,12 @@ fn hard_links_in_project() -> anyhow::Result<()> {
ignore = "windows doesn't support observing changes to hard linked files."
)]
fn hard_links_to_target_outside_project() -> anyhow::Result<()> {
let mut case = setup(|root: &SystemPath, project: &SystemPath| {
let foo_path = root.join("foo.py");
let mut case = setup(|context: &SetupContext| {
let foo_path = context.join_root_path("foo.py");
std::fs::write(foo_path.as_std_path(), "print('Version 1')")?;
// Create a hardlink to `foo`
let bar_path = project.join("bar.py");
let bar_path = context.join_project_path("bar.py");
std::fs::hard_link(foo_path.as_std_path(), bar_path.as_std_path())
.context("Failed to create hard link from foo.py -> bar.py")?;
@@ -1088,9 +1235,9 @@ mod unix {
ignore = "FSEvents doesn't emit change events for symlinked directories outside of the watched paths."
)]
fn symlink_target_outside_watched_paths() -> anyhow::Result<()> {
let mut case = setup(|root: &SystemPath, project: &SystemPath| {
let mut case = setup(|context: &SetupContext| {
// Set up the symlink target.
let link_target = root.join("bar");
let link_target = context.join_root_path("bar");
std::fs::create_dir_all(link_target.as_std_path())
.context("Failed to create link target directory")?;
let baz_original = link_target.join("baz.py");
@@ -1098,7 +1245,7 @@ mod unix {
.context("Failed to write link target file")?;
// Create a symlink inside the project
let bar = project.join("bar");
let bar = context.join_project_path("bar");
std::os::unix::fs::symlink(link_target.as_std_path(), bar.as_std_path())
.context("Failed to create symlink to bar package")?;
@@ -1127,7 +1274,7 @@ mod unix {
update_file(baz_original, "def baz(): print('Version 2')")
.context("Failed to update bar/baz.py")?;
let changes = case.take_watch_changes();
let changes = case.take_watch_changes(event_for_file("baz.py"));
case.apply_changes(changes);
@@ -1169,9 +1316,9 @@ mod unix {
/// ```
#[test]
fn symlink_inside_project() -> anyhow::Result<()> {
let mut case = setup(|_root: &SystemPath, project: &SystemPath| {
let mut case = setup(|context: &SetupContext| {
// Set up the symlink target.
let link_target = project.join("patched/bar");
let link_target = context.join_project_path("patched/bar");
std::fs::create_dir_all(link_target.as_std_path())
.context("Failed to create link target directory")?;
let baz_original = link_target.join("baz.py");
@@ -1179,7 +1326,7 @@ mod unix {
.context("Failed to write link target file")?;
// Create a symlink inside site-packages
let bar_in_project = project.join("bar");
let bar_in_project = context.join_project_path("bar");
std::os::unix::fs::symlink(link_target.as_std_path(), bar_in_project.as_std_path())
.context("Failed to create symlink to bar package")?;
@@ -1259,10 +1406,10 @@ mod unix {
/// ```
#[test]
fn symlinked_module_search_path() -> anyhow::Result<()> {
let mut case = setup_with_search_paths(
|root: &SystemPath, project: &SystemPath| {
let mut case = setup_with_options(
|context: &SetupContext| {
// Set up the symlink target.
let site_packages = root.join("site-packages");
let site_packages = context.join_root_path("site-packages");
let bar = site_packages.join("bar");
std::fs::create_dir_all(bar.as_std_path())
.context("Failed to create bar directory")?;
@@ -1271,7 +1418,8 @@ mod unix {
.context("Failed to write baz.py")?;
// Symlink the site packages in the venv to the global site packages
let venv_site_packages = project.join(".venv/lib/python3.12/site-packages");
let venv_site_packages =
context.join_project_path(".venv/lib/python3.12/site-packages");
std::fs::create_dir_all(venv_site_packages.parent().unwrap())
.context("Failed to create .venv directory")?;
std::os::unix::fs::symlink(
@@ -1282,11 +1430,17 @@ mod unix {
Ok(())
},
|_root, project| SearchPathConfiguration {
site_packages: Some(SitePackages::Known(vec![
project.join(".venv/lib/python3.12/site-packages")
])),
..SearchPathConfiguration::default()
|_context| {
Some(Options {
environment: Some(EnvironmentOptions {
extra_paths: Some(vec![RelativePathBuf::cli(
".venv/lib/python3.12/site-packages",
)]),
python_version: Some(RangedValue::cli(PythonVersion::PY312)),
..EnvironmentOptions::default()
}),
..Options::default()
})
},
)?;
@@ -1346,9 +1500,9 @@ mod unix {
#[test]
fn nested_projects_delete_root() -> anyhow::Result<()> {
let mut case = setup(|root: &SystemPath, project_root: &SystemPath| {
let mut case = setup(|context: &SetupContext| {
std::fs::write(
project_root.join("pyproject.toml").as_std_path(),
context.join_project_path("pyproject.toml").as_std_path(),
r#"
[project]
name = "inner"
@@ -1358,7 +1512,7 @@ fn nested_projects_delete_root() -> anyhow::Result<()> {
)?;
std::fs::write(
root.join("pyproject.toml").as_std_path(),
context.join_root_path("pyproject.toml").as_std_path(),
r#"
[project]
name = "outer"
@@ -1383,3 +1537,79 @@ fn nested_projects_delete_root() -> anyhow::Result<()> {
Ok(())
}
#[test]
fn changes_to_user_configuration() -> anyhow::Result<()> {
let mut _config_dir_override: Option<UserConfigDirectoryOverrideGuard> = None;
let mut case = setup(|context: &SetupContext| {
std::fs::write(
context.join_project_path("pyproject.toml").as_std_path(),
r#"
[project]
name = "test"
"#,
)?;
std::fs::write(
context.join_project_path("foo.py").as_std_path(),
"a = 10 / 0",
)?;
let config_directory = context.join_root_path("home/.config");
std::fs::create_dir_all(config_directory.join("knot").as_std_path())?;
std::fs::write(
config_directory.join("knot/knot.toml").as_std_path(),
r#"
[rules]
division-by-zero = "ignore"
"#,
)?;
_config_dir_override = Some(
context
.system()
.with_user_config_directory(Some(config_directory)),
);
Ok(())
})?;
let foo = case
.system_file(case.project_path("foo.py"))
.expect("foo.py to exist");
let diagnostics = case
.db()
.check_file(foo)
.context("Failed to check project.")?;
assert!(
diagnostics.is_empty(),
"Expected no diagnostics but got: {diagnostics:#?}"
);
// Enable division-by-zero in the user configuration with warning severity
update_file(
case.root_path().join("home/.config/knot/knot.toml"),
r#"
[rules]
division-by-zero = "warn"
"#,
)?;
let changes = case.stop_watch(event_for_file("knot.toml"));
case.apply_changes(changes);
let diagnostics = case
.db()
.check_file(foo)
.context("Failed to check project.")?;
assert!(
diagnostics.len() == 1,
"Expected exactly one diagnostic but got: {diagnostics:#?}"
);
Ok(())
}

View File

@@ -1,5 +1,5 @@
[package]
name = "red_knot_workspace"
name = "red_knot_project"
version = "0.0.0"
edition.workspace = true
rust-version.workspace = true
@@ -12,37 +12,38 @@ license.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
red_knot_python_semantic = { workspace = true }
ruff_cache = { workspace = true }
ruff_db = { workspace = true, features = ["os", "cache", "serde"] }
ruff_db = { workspace = true, features = ["cache", "serde"] }
ruff_macros = { workspace = true }
ruff_python_ast = { workspace = true, features = ["serde"] }
ruff_text_size = { workspace = true }
red_knot_python_semantic = { workspace = true, features = ["serde"] }
red_knot_vendored = { workspace = true }
anyhow = { workspace = true }
crossbeam = { workspace = true }
glob = { workspace = true }
notify = { workspace = true }
pep440_rs = { workspace = true }
pep440_rs = { workspace = true, features = ["version-ranges"] }
rayon = { workspace = true }
rustc-hash = { workspace = true }
salsa = { workspace = true }
schemars = { workspace = true, optional = true }
serde = { workspace = true }
thiserror = { workspace = true }
toml = { workspace = true }
tracing = { workspace = true }
[dev-dependencies]
red_knot_python_semantic = { workspace = true, features = ["serde"] }
ruff_db = { workspace = true, features = ["testing"] }
glob = { workspace = true }
insta = { workspace = true, features = ["redactions", "ron"] }
[features]
default = ["zstd"]
zstd = ["red_knot_vendored/zstd"]
deflate = ["red_knot_vendored/deflate"]
schemars = ["dep:schemars", "ruff_db/schemars", "red_knot_python_semantic/schemars"]
zstd = ["red_knot_vendored/zstd"]
[lints]
workspace = true

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