Skip to content

Commit 88c0ce3

Browse files
authored
Update default and latest Python versions for 3.14 (#20725)
Summary -- Closes #19467 and also removes the warning about using Python 3.14 without preview enabled. I also bumped `PythonVersion::default` to 3.9 because it reaches EOL this month, but we could also defer that for now if we wanted. The first three commits are related to the `latest` bump to 3.14; the fourth commit bumps the default to 3.10. Note that this PR also bumps the default Python version for ty to 3.10 because there was a test asserting that it stays in sync with `ast::PythonVersion`. Test Plan -- Existing tests I spot-checked the ecosystem report, and I believe these are all expected. Inbits doesn't specify a target Python version, so I guess we're applying the default. UP007, UP035, and UP045 all use the new default value to emit new diagnostics.
1 parent 8fb29ea commit 88c0ce3

File tree

88 files changed

+1640
-1123
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+1640
-1123
lines changed

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_ruff_toml_above-2.snap

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ info:
99
- concise
1010
- "--show-settings"
1111
- test.py
12-
snapshot_kind: text
1312
---
1413
success: true
1514
exit_code: 0
@@ -265,7 +264,7 @@ linter.ruff.parenthesize_tuple_in_subscript = false
265264

266265
# Formatter Settings
267266
formatter.exclude = []
268-
formatter.unresolved_target_version = 3.9
267+
formatter.unresolved_target_version = 3.10
269268
formatter.per_file_target_version = {}
270269
formatter.preview = disabled
271270
formatter.line_width = 88
@@ -280,7 +279,7 @@ formatter.docstring_code_line_width = dynamic
280279
# Analyze Settings
281280
analyze.exclude = []
282281
analyze.preview = disabled
283-
analyze.target_version = 3.9
282+
analyze.target_version = 3.10
284283
analyze.string_imports = disabled
285284
analyze.extension = ExtensionMapping({})
286285
analyze.include_dependencies = {}

crates/ruff/tests/cli/snapshots/cli__lint__requires_python_ruff_toml_above.snap

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ info:
99
- concise
1010
- "--show-settings"
1111
- foo/test.py
12-
snapshot_kind: text
1312
---
1413
success: true
1514
exit_code: 0
@@ -265,7 +264,7 @@ linter.ruff.parenthesize_tuple_in_subscript = false
265264

266265
# Formatter Settings
267266
formatter.exclude = []
268-
formatter.unresolved_target_version = 3.9
267+
formatter.unresolved_target_version = 3.10
269268
formatter.per_file_target_version = {}
270269
formatter.preview = disabled
271270
formatter.line_width = 88
@@ -280,7 +279,7 @@ formatter.docstring_code_line_width = dynamic
280279
# Analyze Settings
281280
analyze.exclude = []
282281
analyze.preview = disabled
283-
analyze.target_version = 3.9
282+
analyze.target_version = 3.10
284283
analyze.string_imports = disabled
285284
analyze.extension = ExtensionMapping({})
286285
analyze.include_dependencies = {}

crates/ruff_linter/resources/test/fixtures/pyflakes/F821_18.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@ class Bar:
1414
]
1515

1616

17-
# OK: Allow named expressions in annotations.
17+
# This is no longer allowed on Python 3.14+
1818
x: (y := 1)
1919
print(y)

crates/ruff_linter/resources/test/fixtures/pyflakes/F821_26.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313

1414
# References to a class from inside the class:
1515
class C:
16-
other: C = ... # valid in a `.pyi` stub file, not in a `.py` runtime file
16+
other: C = ... # valid in a `.pyi` stub file, and in a `.py` runtime file with deferred annotations
1717
other2: "C" = ... # always okay
18-
def from_str(self, s: str) -> C: ... # valid in a `.pyi` stub file, not in a `.py` runtime file
18+
def from_str(self, s: str) -> C: ... # valid in a `.pyi` stub file, and in a `.py` runtime file with deferred annotations
1919
def from_str2(self, s: str) -> "C": ... # always okay
2020

2121
# Circular references:
2222
class A:
23-
foo: B # valid in a `.pyi` stub file, not in a `.py` runtime file
23+
foo: B # valid in a `.pyi` stub file, and in a `.py` runtime file with deferred annotations
2424
foo2: "B" # always okay
25-
bar: dict[str, B] # valid in a `.pyi` stub file, not in a `.py` runtime file
25+
bar: dict[str, B] # valid in a `.pyi` stub file, and in a `.py` runtime file with deferred annotations
2626
bar2: dict[str, "A"] # always okay
2727

2828
class B:

crates/ruff_linter/src/linter.rs

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,13 @@ use crate::fix::{FixResult, fix_file};
2727
use crate::message::create_syntax_error_diagnostic;
2828
use crate::noqa::add_noqa;
2929
use crate::package::PackageRoot;
30-
use crate::preview::is_py314_support_enabled;
3130
use crate::registry::Rule;
3231
#[cfg(any(feature = "test-rules", test))]
3332
use crate::rules::ruff::rules::test_rules::{self, TEST_RULES, TestRule};
3433
use crate::settings::types::UnsafeFixes;
3534
use crate::settings::{LinterSettings, TargetVersion, flags};
3635
use crate::source_kind::SourceKind;
37-
use crate::{Locator, directives, fs, warn_user_once};
36+
use crate::{Locator, directives, fs};
3837

3938
pub(crate) mod float;
4039

@@ -442,14 +441,6 @@ pub fn lint_only(
442441
) -> LinterResult {
443442
let target_version = settings.resolve_target_version(path);
444443

445-
if matches!(target_version, TargetVersion(Some(PythonVersion::PY314)))
446-
&& !is_py314_support_enabled(settings)
447-
{
448-
warn_user_once!(
449-
"Support for Python 3.14 is in preview and may undergo breaking changes. Enable `preview` to remove this warning."
450-
);
451-
}
452-
453444
let parsed = source.into_parsed(source_kind, source_type, target_version.parser_version());
454445

455446
// Map row and column locations to byte slices (lazily).
@@ -551,14 +542,6 @@ pub fn lint_fix<'a>(
551542

552543
let target_version = settings.resolve_target_version(path);
553544

554-
if matches!(target_version, TargetVersion(Some(PythonVersion::PY314)))
555-
&& !is_py314_support_enabled(settings)
556-
{
557-
warn_user_once!(
558-
"Support for Python 3.14 is in preview and may undergo breaking changes. Enable `preview` to remove this warning."
559-
);
560-
}
561-
562545
// Continuously fix until the source code stabilizes.
563546
loop {
564547
// Parse once.

crates/ruff_linter/src/preview.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@
77
88
use crate::settings::LinterSettings;
99

10-
pub(crate) const fn is_py314_support_enabled(settings: &LinterSettings) -> bool {
11-
settings.preview.is_enabled()
12-
}
13-
1410
// Rule-specific behavior
1511

1612
// https://github.com/astral-sh/ruff/pull/15541

crates/ruff_linter/src/rules/fastapi/mod.rs

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,12 @@ mod tests {
88
use anyhow::Result;
99
use test_case::test_case;
1010

11+
use ruff_python_ast::PythonVersion;
12+
1113
use crate::registry::Rule;
14+
use crate::settings::LinterSettings;
1215
use crate::test::test_path;
13-
use crate::{assert_diagnostics, settings};
16+
use crate::{assert_diagnostics, assert_diagnostics_diff};
1417

1518
#[test_case(Rule::FastApiRedundantResponseModel, Path::new("FAST001.py"))]
1619
#[test_case(Rule::FastApiNonAnnotatedDependency, Path::new("FAST002_0.py"))]
@@ -20,12 +23,35 @@ mod tests {
2023
let snapshot = format!("{}_{}", rule_code.name(), path.to_string_lossy());
2124
let diagnostics = test_path(
2225
Path::new("fastapi").join(path).as_path(),
23-
&settings::LinterSettings::for_rule(rule_code),
26+
&LinterSettings::for_rule(rule_code),
2427
)?;
2528
assert_diagnostics!(snapshot, diagnostics);
2629
Ok(())
2730
}
2831

32+
#[test_case(Rule::FastApiRedundantResponseModel, Path::new("FAST001.py"))]
33+
#[test_case(Rule::FastApiUnusedPathParameter, Path::new("FAST003.py"))]
34+
fn deferred_annotations_diff(rule_code: Rule, path: &Path) -> Result<()> {
35+
let snapshot = format!(
36+
"deferred_annotations_diff_{}_{}",
37+
rule_code.name(),
38+
path.to_string_lossy()
39+
);
40+
assert_diagnostics_diff!(
41+
snapshot,
42+
Path::new("fastapi").join(path).as_path(),
43+
&LinterSettings {
44+
unresolved_target_version: PythonVersion::PY313.into(),
45+
..LinterSettings::for_rule(rule_code)
46+
},
47+
&LinterSettings {
48+
unresolved_target_version: PythonVersion::PY314.into(),
49+
..LinterSettings::for_rule(rule_code)
50+
},
51+
);
52+
Ok(())
53+
}
54+
2955
// FAST002 autofixes use `typing_extensions` on Python 3.8,
3056
// since `typing.Annotated` was added in Python 3.9
3157
#[test_case(Rule::FastApiNonAnnotatedDependency, Path::new("FAST002_0.py"))]
@@ -34,9 +60,9 @@ mod tests {
3460
let snapshot = format!("{}_{}_py38", rule_code.name(), path.to_string_lossy());
3561
let diagnostics = test_path(
3662
Path::new("fastapi").join(path).as_path(),
37-
&settings::LinterSettings {
38-
unresolved_target_version: ruff_python_ast::PythonVersion::PY38.into(),
39-
..settings::LinterSettings::for_rule(rule_code)
63+
&LinterSettings {
64+
unresolved_target_version: PythonVersion::PY38.into(),
65+
..LinterSettings::for_rule(rule_code)
4066
},
4167
)?;
4268
assert_diagnostics!(snapshot, diagnostics);

0 commit comments

Comments
 (0)