Compare commits

..

9 Commits

Author SHA1 Message Date
Brent Westbrook
e3d26e1a62 expand use instead examples 2025-10-02 13:33:01 -04:00
Brent Westbrook
2caf2987c0 spaces instead of tabs
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>
2025-10-02 11:34:25 -04:00
Brent Westbrook
5dfc47ff3b remove links from readme
since we extract this piece for inclusion in the docs, the links would need to
be relative, but then they wouldn't work in the readme
2025-10-02 11:21:59 -04:00
Brent Westbrook
20cbbf03b8 add a test covering most of the default rules 2025-10-02 10:42:23 -04:00
Brent Westbrook
f707bf6cf8 update snapshots 2025-10-02 09:14:20 -04:00
Brent Westbrook
2230ab07d0 update the documentation to reflect the new defaults 2025-10-02 09:08:47 -04:00
Brent Westbrook
3a779a237e add PEP 765 to B012 docs 2025-10-02 08:59:28 -04:00
Brent Westbrook
cf0d026b41 add new rules to DEFAULT_SELECTORS 2025-10-02 08:56:47 -04:00
Brent Westbrook
1c5a9681a5 fix escaped less than and removal date for PYI057 2025-10-02 08:55:44 -04:00
22 changed files with 189 additions and 190 deletions

View File

@@ -932,7 +932,7 @@ jobs:
tool: cargo-codspeed
- name: "Build benchmarks"
run: cargo codspeed build --features "codspeed,instrumented" --no-default-features -p ruff_benchmark --bench formatter --bench lexer --bench linter --bench parser
run: cargo codspeed build --features "codspeed,instrumented" --no-default-features -p ruff_benchmark formatter lexer linter parser
- name: "Run benchmarks"
uses: CodSpeedHQ/action@653fdc30e6c40ffd9739e40c8a0576f4f4523ca1 # v4.0.1
@@ -967,7 +967,7 @@ jobs:
tool: cargo-codspeed
- name: "Build benchmarks"
run: cargo codspeed build --features "codspeed,instrumented" --no-default-features -p ruff_benchmark --bench ty
run: cargo codspeed build --features "codspeed,instrumented" --no-default-features -p ruff_benchmark ty
- name: "Run benchmarks"
uses: CodSpeedHQ/action@653fdc30e6c40ffd9739e40c8a0576f4f4523ca1 # v4.0.1

View File

@@ -1,48 +1,5 @@
# Changelog
## 0.13.3
Released on 2025-10-02.
### Preview features
- Display diffs for `ruff format --check` and add support for different output formats ([#20443](https://github.com/astral-sh/ruff/pull/20443))
- \[`pyflakes`\] Handle some common submodule import situations for `unused-import` (`F401`) ([#20200](https://github.com/astral-sh/ruff/pull/20200))
- \[`ruff`\] Do not flag `%r` + `repr()` combinations (`RUF065`) ([#20600](https://github.com/astral-sh/ruff/pull/20600))
### Bug fixes
- \[`cli`\] Add conflict between `--add-noqa` and `--diff` options ([#20642](https://github.com/astral-sh/ruff/pull/20642))
- \[`pylint`\] Exempt required imports from `PLR0402` ([#20381](https://github.com/astral-sh/ruff/pull/20381))
- \[`pylint`\] Fix missing `max-nested-blocks` in settings display ([#20574](https://github.com/astral-sh/ruff/pull/20574))
- \[`pyupgrade`\] Prevent infinite loop with `I002` and `UP026` ([#20634](https://github.com/astral-sh/ruff/pull/20634))
### Rule changes
- \[`flake8-simplify`\] Improve help message clarity (`SIM105`) ([#20548](https://github.com/astral-sh/ruff/pull/20548))
### Documentation
- Add the *The Basics* title back to CONTRIBUTING.md ([#20624](https://github.com/astral-sh/ruff/pull/20624))
- Fixed documentation for try_consider_else ([#20587](https://github.com/astral-sh/ruff/pull/20587))
- \[`isort`\] Clarify dependency between `order-by-type` and `case-sensitive` settings ([#20559](https://github.com/astral-sh/ruff/pull/20559))
- \[`pylint`\] Clarify fix safety to include left-hand hashability (`PLR6201`) ([#20518](https://github.com/astral-sh/ruff/pull/20518))
### Other changes
- \[`playground`\] Fix quick fixes for empty ranges in playground ([#20599](https://github.com/astral-sh/ruff/pull/20599))
### Contributors
- [@TaKO8Ki](https://github.com/TaKO8Ki)
- [@ntBre](https://github.com/ntBre)
- [@dylwil3](https://github.com/dylwil3)
- [@MichaReiser](https://github.com/MichaReiser)
- [@danparizher](https://github.com/danparizher)
- [@LilMonk](https://github.com/LilMonk)
- [@mgiovani](https://github.com/mgiovani)
- [@IDrokin117](https://github.com/IDrokin117)
## 0.13.2
Released on 2025-09-25.

6
Cargo.lock generated
View File

@@ -2738,7 +2738,7 @@ dependencies = [
[[package]]
name = "ruff"
version = "0.13.3"
version = "0.13.2"
dependencies = [
"anyhow",
"argfile",
@@ -2994,7 +2994,7 @@ dependencies = [
[[package]]
name = "ruff_linter"
version = "0.13.3"
version = "0.13.2"
dependencies = [
"aho-corasick",
"anyhow",
@@ -3348,7 +3348,7 @@ dependencies = [
[[package]]
name = "ruff_wasm"
version = "0.13.3"
version = "0.13.2"
dependencies = [
"console_error_panic_hook",
"console_log",

View File

@@ -148,8 +148,8 @@ curl -LsSf https://astral.sh/ruff/install.sh | sh
powershell -c "irm https://astral.sh/ruff/install.ps1 | iex"
# For a specific version.
curl -LsSf https://astral.sh/ruff/0.13.3/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.13.3/install.ps1 | iex"
curl -LsSf https://astral.sh/ruff/0.13.2/install.sh | sh
powershell -c "irm https://astral.sh/ruff/0.13.2/install.ps1 | iex"
```
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
@@ -182,7 +182,7 @@ Ruff can also be used as a [pre-commit](https://pre-commit.com/) hook via [`ruff
```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.13.3
rev: v0.13.2
hooks:
# Run the linter.
- id: ruff-check
@@ -311,9 +311,11 @@ for more on the linting and formatting commands, respectively.
isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in
Rust as a first-party feature.
By default, Ruff enables Flake8's `F` rules, along with a subset of the `E` rules, omitting any
stylistic rules that overlap with the use of a formatter, like `ruff format` or
[Black](https://github.com/psf/black).
By default, Ruff enables Flake8's `F` rules, along with a subset of the `E`
rules, omitting any stylistic rules that overlap with the use of a formatter,
like `ruff format` or [Black](https://github.com/psf/black). Ruff also enables
`B012`, which corresponds to a `SyntaxWarning`, and `PYI057`, which flags
usage of some long-deprecated APIs in the standard library.
If you're just getting started with Ruff, **the default rule set is a great place to start**: it
catches a wide variety of common errors (like unused imports) with zero configuration.

View File

@@ -31,7 +31,6 @@ extend-ignore-re = [
"typ",
# TODO: Remove this once the `TYP` redirects are removed from `rule_redirects.rs`
"TYP",
"ntBre"
]
[default.extend-identifiers]

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff"
version = "0.13.3"
version = "0.13.2"
publish = true
authors = { workspace = true }
edition = { workspace = true }

View File

@@ -21,12 +21,13 @@ fn lint_select() {
specific prefixes. `ignore` takes precedence over `select` if the
same prefix appears in both.
Default value: ["E4", "E7", "E9", "F"]
Default value: ["E4", "E7", "E9", "F", "B012", "PYI057"]
Type: list[RuleSelector]
Example usage:
```toml
# On top of the defaults (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).
select = ["E4", "E7", "E9", "F", "B", "Q"]
# On top of the defaults (`E4`, E7`, `E9`, `F`, `B012`, and `PYI057`),
# enable flake8-bugbear (`B`) and flake8-quotes (`Q`).
select = ["E4", "E7", "E9", "F", "PYI057", "B", "Q"]
```
----- stderr -----
@@ -43,10 +44,10 @@ fn lint_select_json() {
----- stdout -----
{
"doc": "A list of rule codes or prefixes to enable. Prefixes can specify exact\nrules (like `F841`), entire categories (like `F`), or anything in\nbetween.\n\nWhen breaking ties between enabled and disabled rules (via `select` and\n`ignore`, respectively), more specific prefixes override less\nspecific prefixes. `ignore` takes precedence over `select` if the\nsame prefix appears in both.",
"default": "[\"E4\", \"E7\", \"E9\", \"F\"]",
"default": "[\"E4\", \"E7\", \"E9\", \"F\", \"B012\", \"PYI057\"]",
"value_type": "list[RuleSelector]",
"scope": null,
"example": "# On top of the defaults (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"B\", \"Q\"]",
"example": "# On top of the defaults (`E4`, E7`, `E9`, `F`, `B012`, and `PYI057`),\n# enable flake8-bugbear (`B`) and flake8-quotes (`Q`).\nselect = [\"E4\", \"E7\", \"E9\", \"F\", \"PYI057\", \"B\", \"Q\"]",
"deprecated": null
}

View File

@@ -6595,3 +6595,38 @@ fn supported_file_extensions_preview_enabled() -> Result<()> {
});
Ok(())
}
#[test]
fn default_rules() {
let stdin = "\
def f():
try:
from typing import ByteString as TypingByteString # PYI057
from collections.abc import ByteString as CollectionsByteString # PYI057
except:
pass
finally:
return # B012
";
assert_cmd_snapshot!(
Command::new(get_cargo_bin(BIN_NAME))
.args(["check", "--output-format=concise", "--no-cache", "--stdin-filename=test.py", "-"])
.pass_stdin(stdin),
@r"
success: false
exit_code: 1
----- stdout -----
test.py:3:23: PYI057 Do not use `typing.ByteString`, which has unclear semantics and is deprecated
test.py:3:37: F401 [*] `typing.ByteString` imported but unused
test.py:4:32: PYI057 Do not use `collections.abc.ByteString`, which has unclear semantics and is deprecated
test.py:4:46: F401 [*] `collections.abc.ByteString` imported but unused
test.py:5:3: E722 Do not use bare `except`
test.py:8:4: B012 `return` inside `finally` blocks cause exceptions to be silenced
Found 6 errors.
[*] 2 fixable with the `--fix` option.
----- stderr -----
",
);
}

View File

@@ -65,6 +65,8 @@ file_resolver.project_root = "<temp_dir>/"
linter.exclude = []
linter.project_root = "<temp_dir>/"
linter.rules.enabled = [
jump-statement-in-finally (B012),
byte-string-usage (PYI057),
multiple-imports-on-one-line (E401),
module-import-not-at-top-of-file (E402),
multiple-statements-on-one-line-colon (E701),
@@ -126,6 +128,8 @@ linter.rules.enabled = [
raise-not-implemented (F901),
]
linter.rules.should_fix = [
jump-statement-in-finally (B012),
byte-string-usage (PYI057),
multiple-imports-on-one-line (E401),
module-import-not-at-top-of-file (E402),
multiple-statements-on-one-line-colon (E701),

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_linter"
version = "0.13.3"
version = "0.13.2"
publish = false
authors = { workspace = true }
edition = { workspace = true }

View File

@@ -18,6 +18,9 @@ use crate::checkers::ast::Checker;
/// `break`, `continue`, or `return` statement is reached in a `finally` block,
/// any exception raised in the `try` or `except` blocks will be silenced.
///
/// [PEP 765](https://peps.python.org/pep-0765/) additionally made this a `SyntaxWarning` starting
/// in Python 3.14. It may become a `SyntaxError` in the future.
///
/// ## Example
/// ```python
/// def speed(distance, time):

View File

@@ -11,20 +11,32 @@ use crate::{FixAvailability, Violation};
///
/// ## Why is this bad?
/// `ByteString` has been deprecated since Python 3.9 and will be removed in
/// Python 3.14. The Python documentation recommends using either
/// Python 3.17. The Python documentation recommends using either
/// `collections.abc.Buffer` (or the `typing_extensions` backport
/// on Python <3.12) or a union like `bytes | bytearray | memoryview` instead.
/// on Python versions before 3.12) or a union like `bytes | bytearray | memoryview` instead.
///
/// ## Example
/// ```python
/// from typing import ByteString
/// ```
///
/// Use instead:
/// On Python versions after 3.12, use the `Buffer` type from the standard library instead:
/// ```python
/// from collections.abc import Buffer
/// ```
///
/// For earlier Python versions, you can use `typing_extensions`:
/// ```python
/// from typing_extensions import Buffer
/// ```
///
/// or a union:
/// ```python
/// from typing import Union
///
/// x: Union[bytes, bytearray, memoryview]
/// ```
///
/// ## References
/// - [Python documentation: The `ByteString` type](https://docs.python.org/3/library/typing.html#typing.ByteString)
#[derive(ViolationMetadata)]

View File

@@ -369,6 +369,17 @@ pub const DEFAULT_SELECTORS: &[RuleSelector] = &[
prefix: RuleCodePrefix::Pycodestyle(codes::Pycodestyle::E9),
redirected_from: None,
},
// Additionally include rules that will correspond to CPython errors in the future:
// - B012 is a syntax warning in 3.14 and will become an error in the future
// - PYI057 reports deprecated members of the standard library
RuleSelector::Rule {
prefix: RuleCodePrefix::Flake8Bugbear(codes::Flake8Bugbear::_012),
redirected_from: None,
},
RuleSelector::Rule {
prefix: RuleCodePrefix::Flake8Pyi(codes::Flake8Pyi::_057),
redirected_from: None,
},
];
pub const TASK_TAGS: &[&str] = &["TODO", "FIXME", "XXX"];

View File

@@ -1,6 +1,6 @@
[package]
name = "ruff_wasm"
version = "0.13.3"
version = "0.13.2"
publish = false
authors = { workspace = true }
edition = { workspace = true }

View File

@@ -804,11 +804,12 @@ pub struct LintCommonOptions {
/// specific prefixes. `ignore` takes precedence over `select` if the
/// same prefix appears in both.
#[option(
default = r#"["E4", "E7", "E9", "F"]"#,
default = r#"["E4", "E7", "E9", "F", "B012", "PYI057"]"#,
value_type = "list[RuleSelector]",
example = r#"
# On top of the defaults (`E4`, E7`, `E9`, and `F`), enable flake8-bugbear (`B`) and flake8-quotes (`Q`).
select = ["E4", "E7", "E9", "F", "B", "Q"]
# On top of the defaults (`E4`, E7`, `E9`, `F`, `B012`, and `PYI057`),
# enable flake8-bugbear (`B`) and flake8-quotes (`Q`).
select = ["E4", "E7", "E9", "F", "PYI057", "B", "Q"]
"#
)]
pub select: Option<Vec<RuleSelector>>,

View File

@@ -139,7 +139,8 @@ reveal_type(f(A())) # revealed: A
reveal_type(f(*(A(),))) # revealed: A
reveal_type(f(B())) # revealed: A
reveal_type(f(*(B(),))) # revealed: A
# TODO: revealed: A
reveal_type(f(*(B(),))) # revealed: Unknown
# But, in this case, the arity check filters out the first overload, so we only have one match:
reveal_type(f(B(), 1)) # revealed: B
@@ -550,13 +551,16 @@ from overloaded import MyEnumSubclass, ActualEnum, f
def _(actual_enum: ActualEnum, my_enum_instance: MyEnumSubclass):
reveal_type(f(actual_enum)) # revealed: Both
reveal_type(f(*(actual_enum,))) # revealed: Both
# TODO: revealed: Both
reveal_type(f(*(actual_enum,))) # revealed: Unknown
reveal_type(f(ActualEnum.A)) # revealed: OnlyA
reveal_type(f(*(ActualEnum.A,))) # revealed: OnlyA
# TODO: revealed: OnlyA
reveal_type(f(*(ActualEnum.A,))) # revealed: Unknown
reveal_type(f(ActualEnum.B)) # revealed: OnlyB
reveal_type(f(*(ActualEnum.B,))) # revealed: OnlyB
# TODO: revealed: OnlyB
reveal_type(f(*(ActualEnum.B,))) # revealed: Unknown
reveal_type(f(my_enum_instance)) # revealed: MyEnumSubclass
reveal_type(f(*(my_enum_instance,))) # revealed: MyEnumSubclass
@@ -1093,10 +1097,12 @@ reveal_type(f(*(1,))) # revealed: str
def _(list_int: list[int], list_any: list[Any]):
reveal_type(f(list_int)) # revealed: int
reveal_type(f(*(list_int,))) # revealed: int
# TODO: revealed: int
reveal_type(f(*(list_int,))) # revealed: Unknown
reveal_type(f(list_any)) # revealed: int
reveal_type(f(*(list_any,))) # revealed: int
# TODO: revealed: int
reveal_type(f(*(list_any,))) # revealed: Unknown
```
### Single list argument (ambiguous)
@@ -1130,7 +1136,8 @@ def _(list_int: list[int], list_any: list[Any]):
# All materializations of `list[int]` are assignable to `list[int]`, so it matches the first
# overload.
reveal_type(f(list_int)) # revealed: int
reveal_type(f(*(list_int,))) # revealed: int
# TODO: revealed: int
reveal_type(f(*(list_int,))) # revealed: Unknown
# All materializations of `list[Any]` are assignable to `list[int]` and `list[Any]`, but the
# return type of first and second overloads are not equivalent, so the overload matching
@@ -1163,21 +1170,25 @@ reveal_type(f("a")) # revealed: str
reveal_type(f(*("a",))) # revealed: str
reveal_type(f((1, "b"))) # revealed: int
reveal_type(f(*((1, "b"),))) # revealed: int
# TODO: revealed: int
reveal_type(f(*((1, "b"),))) # revealed: Unknown
reveal_type(f((1, 2))) # revealed: int
reveal_type(f(*((1, 2),))) # revealed: int
# TODO: revealed: int
reveal_type(f(*((1, 2),))) # revealed: Unknown
def _(int_str: tuple[int, str], int_any: tuple[int, Any], any_any: tuple[Any, Any]):
# All materializations are assignable to first overload, so second and third overloads are
# eliminated
reveal_type(f(int_str)) # revealed: int
reveal_type(f(*(int_str,))) # revealed: int
# TODO: revealed: int
reveal_type(f(*(int_str,))) # revealed: Unknown
# All materializations are assignable to second overload, so the third overload is eliminated;
# the return type of first and second overload is equivalent
reveal_type(f(int_any)) # revealed: int
reveal_type(f(*(int_any,))) # revealed: int
# TODO: revealed: int
reveal_type(f(*(int_any,))) # revealed: Unknown
# All materializations of `tuple[Any, Any]` are assignable to the parameters of all the
# overloads, but the return types aren't equivalent, so the overload matching is ambiguous
@@ -1255,22 +1266,26 @@ def _(list_int: list[int], list_any: list[Any], int_str: tuple[int, str], int_an
# All materializations of both argument types are assignable to the first overload, so the
# second and third overloads are filtered out
reveal_type(f(list_int, int_str)) # revealed: A
reveal_type(f(*(list_int, int_str))) # revealed: A
# TODO: revealed: A
reveal_type(f(*(list_int, int_str))) # revealed: Unknown
# All materialization of first argument is assignable to first overload and for the second
# argument, they're assignable to the second overload, so the third overload is filtered out
reveal_type(f(list_int, int_any)) # revealed: A
reveal_type(f(*(list_int, int_any))) # revealed: A
# TODO: revealed: A
reveal_type(f(*(list_int, int_any))) # revealed: Unknown
# All materialization of first argument is assignable to second overload and for the second
# argument, they're assignable to the first overload, so the third overload is filtered out
reveal_type(f(list_any, int_str)) # revealed: A
reveal_type(f(*(list_any, int_str))) # revealed: A
# TODO: revealed: A
reveal_type(f(*(list_any, int_str))) # revealed: Unknown
# All materializations of both arguments are assignable to the second overload, so the third
# overload is filtered out
reveal_type(f(list_any, int_any)) # revealed: A
reveal_type(f(*(list_any, int_any))) # revealed: A
# TODO: revealed: A
reveal_type(f(*(list_any, int_any))) # revealed: Unknown
# All materializations of first argument is assignable to the second overload and for the second
# argument, they're assignable to the third overload, so no overloads are filtered out; the
@@ -1301,7 +1316,8 @@ from overloaded import f
def _(literal: LiteralString, string: str, any: Any):
reveal_type(f(literal)) # revealed: LiteralString
reveal_type(f(*(literal,))) # revealed: LiteralString
# TODO: revealed: LiteralString
reveal_type(f(*(literal,))) # revealed: Unknown
reveal_type(f(string)) # revealed: str
reveal_type(f(*(string,))) # revealed: str
@@ -1339,10 +1355,12 @@ from overloaded import f
def _(list_int: list[int], list_str: list[str], list_any: list[Any], any: Any):
reveal_type(f(list_int)) # revealed: A
reveal_type(f(*(list_int,))) # revealed: A
# TODO: revealed: A
reveal_type(f(*(list_int,))) # revealed: Unknown
reveal_type(f(list_str)) # revealed: str
reveal_type(f(*(list_str,))) # revealed: str
# TODO: Should be `str`
reveal_type(f(*(list_str,))) # revealed: Unknown
reveal_type(f(list_any)) # revealed: Unknown
reveal_type(f(*(list_any,))) # revealed: Unknown
@@ -1543,10 +1561,12 @@ def _(any: Any):
reveal_type(f(*(any,), flag=False)) # revealed: str
def _(args: tuple[Any, Literal[True]]):
reveal_type(f(*args)) # revealed: int
# TODO: revealed: int
reveal_type(f(*args)) # revealed: Unknown
def _(args: tuple[Any, Literal[False]]):
reveal_type(f(*args)) # revealed: str
# TODO: revealed: str
reveal_type(f(*args)) # revealed: Unknown
```
### Argument type expansion

View File

@@ -32,7 +32,7 @@ use crate::types::tuple::{TupleLength, TupleType};
use crate::types::{
BoundMethodType, ClassLiteral, DataclassParams, FieldInstance, KnownBoundMethodType,
KnownClass, KnownInstanceType, MemberLookupPolicy, PropertyInstanceType, SpecialFormType,
TrackedConstraintSet, TypeAliasType, TypeContext, TypeMapping, UnionBuilder, UnionType,
TrackedConstraintSet, TypeAliasType, TypeContext, TypeMapping, UnionType,
WrapperDescriptorKind, enums, ide_support, todo_type,
};
use ruff_db::diagnostic::{Annotation, Diagnostic, SubDiagnostic, SubDiagnosticSeverity};
@@ -1588,14 +1588,6 @@ impl<'db> CallableBinding<'db> {
arguments: &CallArguments<'_, 'db>,
matching_overload_indexes: &[usize],
) {
// The maximum number of parameters across all the overloads that are being considered
// for filtering.
let max_parameter_count = matching_overload_indexes
.iter()
.map(|&index| self.overloads[index].signature.parameters().len())
.max()
.unwrap_or(0);
// These are the parameter indexes that matches the arguments that participate in the
// filtering process.
//
@@ -1603,67 +1595,41 @@ impl<'db> CallableBinding<'db> {
// gradual equivalent to the parameter types at the same index for other overloads.
let mut participating_parameter_indexes = HashSet::new();
// The parameter types at each index for the first overload containing a parameter at
// that index.
let mut first_parameter_types: Vec<Option<Type<'db>>> = vec![None; max_parameter_count];
for argument_index in 0..arguments.len() {
for overload_index in matching_overload_indexes {
let overload = &self.overloads[*overload_index];
for &parameter_index in &overload.argument_matches[argument_index].parameters {
// TODO: For an unannotated `self` / `cls` parameter, the type should be
// `typing.Self` / `type[typing.Self]`
let current_parameter_type = overload.signature.parameters()[parameter_index]
.annotated_type()
.unwrap_or(Type::unknown());
let first_parameter_type = &mut first_parameter_types[parameter_index];
if let Some(first_parameter_type) = first_parameter_type {
if !first_parameter_type.is_equivalent_to(db, current_parameter_type) {
participating_parameter_indexes.insert(parameter_index);
}
} else {
*first_parameter_type = Some(current_parameter_type);
}
}
}
}
let mut union_argument_type_builders = std::iter::repeat_with(|| UnionBuilder::new(db))
.take(max_parameter_count)
.collect::<Vec<_>>();
for (argument_index, argument_type) in arguments.iter_types().enumerate() {
for overload_index in matching_overload_indexes {
let overload = &self.overloads[*overload_index];
for (parameter_index, variadic_argument_type) in
overload.argument_matches[argument_index].iter()
{
if !participating_parameter_indexes.contains(&parameter_index) {
continue;
}
union_argument_type_builders[parameter_index].add_in_place(
variadic_argument_type
.unwrap_or(argument_type)
.top_materialization(db),
);
}
}
}
// These only contain the top materialized argument types for the corresponding
// participating parameter indexes.
let top_materialized_argument_type = Type::heterogeneous_tuple(
db,
union_argument_type_builders
.into_iter()
.filter_map(|builder| {
if builder.is_empty() {
None
let mut top_materialized_argument_types = vec![];
for (argument_index, argument_type) in arguments.iter_types().enumerate() {
let mut first_parameter_type: Option<Type<'db>> = None;
let mut participating_parameter_index = None;
'overload: for overload_index in matching_overload_indexes {
let overload = &self.overloads[*overload_index];
for parameter_index in &overload.argument_matches[argument_index].parameters {
// TODO: For an unannotated `self` / `cls` parameter, the type should be
// `typing.Self` / `type[typing.Self]`
let current_parameter_type = overload.signature.parameters()[*parameter_index]
.annotated_type()
.unwrap_or(Type::unknown());
if let Some(first_parameter_type) = first_parameter_type {
if !first_parameter_type.is_equivalent_to(db, current_parameter_type) {
participating_parameter_index = Some(*parameter_index);
break 'overload;
}
} else {
Some(builder.build())
first_parameter_type = Some(current_parameter_type);
}
}),
);
}
}
if let Some(parameter_index) = participating_parameter_index {
participating_parameter_indexes.insert(parameter_index);
top_materialized_argument_types.push(argument_type.top_materialization(db));
}
}
let top_materialized_argument_type =
Type::heterogeneous_tuple(db, top_materialized_argument_types);
// A flag to indicate whether we've found the overload that makes the remaining overloads
// unmatched for the given argument types.
@@ -1674,22 +1640,15 @@ impl<'db> CallableBinding<'db> {
self.overloads[*current_index].mark_as_unmatched_overload();
continue;
}
let mut union_parameter_types = std::iter::repeat_with(|| UnionBuilder::new(db))
.take(max_parameter_count)
.collect::<Vec<_>>();
// The number of parameters that have been skipped because they don't participate in
// the filtering process. This is used to make sure the types are added to the
// corresponding parameter index in `union_parameter_types`.
let mut skipped_parameters = 0;
let mut parameter_types = Vec::with_capacity(arguments.len());
for argument_index in 0..arguments.len() {
// The parameter types at the current argument index.
let mut current_parameter_types = vec![];
for overload_index in &matching_overload_indexes[..=upto] {
let overload = &self.overloads[*overload_index];
for parameter_index in &overload.argument_matches[argument_index].parameters {
if !participating_parameter_indexes.contains(parameter_index) {
skipped_parameters += 1;
// This parameter doesn't participate in the filtering process.
continue;
}
// TODO: For an unannotated `self` / `cls` parameter, the type should be
@@ -1705,24 +1664,17 @@ impl<'db> CallableBinding<'db> {
parameter_type =
parameter_type.apply_specialization(db, inherited_specialization);
}
union_parameter_types[parameter_index.saturating_sub(skipped_parameters)]
.add_in_place(parameter_type);
current_parameter_types.push(parameter_type);
}
}
if current_parameter_types.is_empty() {
continue;
}
parameter_types.push(UnionType::from_elements(db, current_parameter_types));
}
let parameter_types = Type::heterogeneous_tuple(
db,
union_parameter_types.into_iter().filter_map(|builder| {
if builder.is_empty() {
None
} else {
Some(builder.build())
}
}),
);
if top_materialized_argument_type.is_assignable_to(db, parameter_types) {
if top_materialized_argument_type
.is_assignable_to(db, Type::heterogeneous_tuple(db, parameter_types))
{
filter_remaining_overloads = true;
}
}

View File

@@ -51,10 +51,12 @@ If left unspecified, Ruff's default configuration is equivalent to:
target-version = "py39"
[tool.ruff.lint]
# Enable Pyflakes (`F`) and a subset of the pycodestyle (`E`) codes by default.
# Enable Pyflakes (`F`), a subset of the pycodestyle (`E`) codes,
# and a couple of other codes corresponding to CPython deprecations
# and syntax warnings by default.
# Unlike Flake8, Ruff doesn't enable pycodestyle warnings (`W`) or
# McCabe complexity (`C901`) by default.
select = ["E4", "E7", "E9", "F"]
select = ["E4", "E7", "E9", "F", "PYI057", "B012"]
ignore = []
# Allow fix for all enabled rules (when `--fix`) is provided.

View File

@@ -80,7 +80,7 @@ You can add the following configuration to `.gitlab-ci.yml` to run a `ruff forma
stage: build
interruptible: true
image:
name: ghcr.io/astral-sh/ruff:0.13.3-alpine
name: ghcr.io/astral-sh/ruff:0.13.2-alpine
before_script:
- cd $CI_PROJECT_DIR
- ruff --version
@@ -106,7 +106,7 @@ Ruff can be used as a [pre-commit](https://pre-commit.com) hook via [`ruff-pre-c
```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.13.3
rev: v0.13.2
hooks:
# Run the linter.
- id: ruff-check
@@ -119,7 +119,7 @@ To enable lint fixes, add the `--fix` argument to the lint hook:
```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.13.3
rev: v0.13.2
hooks:
# Run the linter.
- id: ruff-check
@@ -133,7 +133,7 @@ To avoid running on Jupyter Notebooks, remove `jupyter` from the list of allowed
```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.13.3
rev: v0.13.2
hooks:
# Run the linter.
- id: ruff-check

View File

@@ -369,7 +369,7 @@ This tutorial has focused on Ruff's command-line interface, but Ruff can also be
```yaml
- repo: https://github.com/astral-sh/ruff-pre-commit
# Ruff version.
rev: v0.13.3
rev: v0.13.2
hooks:
# Run the linter.
- id: ruff

View File

@@ -4,7 +4,7 @@ build-backend = "maturin"
[project]
name = "ruff"
version = "0.13.3"
version = "0.13.2"
description = "An extremely fast Python linter and code formatter, written in Rust."
authors = [{ name = "Astral Software Inc.", email = "hey@astral.sh" }]
readme = "README.md"

View File

@@ -1,6 +1,6 @@
[project]
name = "scripts"
version = "0.13.3"
version = "0.13.2"
description = ""
authors = ["Charles Marsh <charlie.r.marsh@gmail.com>"]