Skip to content

Commit fadf6e2

Browse files
Lee-WGlyphack
authored andcommitted
[airflow] Apply try-catch guard to all AIR3 rules (AIR3) (astral-sh#17887)
<!-- Thank you for contributing to Ruff! To help us out with reviewing, please consider the following: - Does this pull request include a summary of the change? (See below.) - Does this pull request include a descriptive title? - Does this pull request include references to any relevant issues? --> ## Summary <!-- What's the purpose of the change? What does it do, and why? --> If a try-catch block guards the names, we don't raise warnings. During this change, I discovered that some of the replacement types were missed. Thus, I extend the fix to types other than AutoImport as well ## Test Plan <!-- How was it tested? --> Test fixtures are added and updated.
1 parent 4a4fd8c commit fadf6e2

14 files changed

+129
-53
lines changed
Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,8 @@
11
from __future__ import annotations
22

33
try:
4-
from airflow.sdk import Asset
4+
from airflow.assets.manager import AssetManager
55
except ModuleNotFoundError:
6-
from airflow.datasets import Dataset as Asset
6+
from airflow.datasets.manager import DatasetManager as AssetManager
77

8-
Asset
9-
10-
try:
11-
from airflow.sdk import Asset
12-
except ModuleNotFoundError:
13-
from airflow import datasets
14-
15-
Asset = datasets.Dataset
16-
17-
asset = Asset()
8+
AssetManager()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from __future__ import annotations
2+
3+
try:
4+
from airflow.providers.http.operators.http import HttpOperator
5+
except ModuleNotFoundError:
6+
from airflow.operators.http_operator import SimpleHttpOperator as HttpOperator
7+
8+
HttpOperator()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from __future__ import annotations
2+
3+
try:
4+
from airflow.sdk import Asset
5+
except ModuleNotFoundError:
6+
from airflow.datasets import Dataset as Asset
7+
8+
Asset()
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
from __future__ import annotations
2+
3+
try:
4+
from airflow.providers.standard.triggers.file import FileTrigger
5+
except ModuleNotFoundError:
6+
from airflow.triggers.file import FileTrigger
7+
8+
FileTrigger()

crates/ruff_linter/src/rules/airflow/helpers.rs

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ pub(crate) enum ProviderReplacement {
4545

4646
pub(crate) fn is_guarded_by_try_except(
4747
expr: &Expr,
48-
replacement: &Replacement,
48+
module: &str,
49+
name: &str,
4950
semantic: &SemanticModel,
5051
) -> bool {
5152
match expr {
@@ -63,7 +64,7 @@ pub(crate) fn is_guarded_by_try_except(
6364
if !suspended_exceptions.contains(Exceptions::ATTRIBUTE_ERROR) {
6465
return false;
6566
}
66-
try_block_contains_undeprecated_attribute(try_node, replacement, semantic)
67+
try_block_contains_undeprecated_attribute(try_node, module, name, semantic)
6768
}
6869
Expr::Name(ExprName { id, .. }) => {
6970
let Some(binding_id) = semantic.lookup_symbol(id.as_str()) else {
@@ -89,7 +90,7 @@ pub(crate) fn is_guarded_by_try_except(
8990
{
9091
return false;
9192
}
92-
try_block_contains_undeprecated_import(try_node, replacement)
93+
try_block_contains_undeprecated_import(try_node, module, name)
9394
}
9495
_ => false,
9596
}
@@ -100,12 +101,10 @@ pub(crate) fn is_guarded_by_try_except(
100101
/// member is being accessed from the non-deprecated location?
101102
fn try_block_contains_undeprecated_attribute(
102103
try_node: &StmtTry,
103-
replacement: &Replacement,
104+
module: &str,
105+
name: &str,
104106
semantic: &SemanticModel,
105107
) -> bool {
106-
let Replacement::AutoImport { module, name } = replacement else {
107-
return false;
108-
};
109108
let undeprecated_qualified_name = {
110109
let mut builder = QualifiedNameBuilder::default();
111110
for part in module.split('.') {
@@ -122,10 +121,7 @@ fn try_block_contains_undeprecated_attribute(
122121
/// Given an [`ast::StmtTry`] node, does the `try` branch of that node
123122
/// contain any [`ast::StmtImportFrom`] nodes that indicate the airflow
124123
/// member is being imported from the non-deprecated location?
125-
fn try_block_contains_undeprecated_import(try_node: &StmtTry, replacement: &Replacement) -> bool {
126-
let Replacement::AutoImport { module, name } = replacement else {
127-
return false;
128-
};
124+
fn try_block_contains_undeprecated_import(try_node: &StmtTry, module: &str, name: &str) -> bool {
129125
let mut import_searcher = ImportSearcher::new(module, name);
130126
import_searcher.visit_body(&try_node.body);
131127
import_searcher.found_import

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,12 @@ mod tests {
4646
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR302_sqlite.py"))]
4747
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR302_zendesk.py"))]
4848
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR302_standard.py"))]
49+
#[test_case(Rule::Airflow3MovedToProvider, Path::new("AIR302_try.py"))]
4950
#[test_case(Rule::Airflow3SuggestedUpdate, Path::new("AIR311_args.py"))]
5051
#[test_case(Rule::Airflow3SuggestedUpdate, Path::new("AIR311_names.py"))]
52+
#[test_case(Rule::Airflow3SuggestedUpdate, Path::new("AIR311_try.py"))]
5153
#[test_case(Rule::Airflow3SuggestedToMoveToProvider, Path::new("AIR312.py"))]
54+
#[test_case(Rule::Airflow3SuggestedToMoveToProvider, Path::new("AIR312_try.py"))]
5255
fn rules(rule_code: Rule, path: &Path) -> Result<()> {
5356
let snapshot = format!("{}_{}", rule_code.noqa_code(), path.to_string_lossy());
5457
let diagnostics = test_path(

crates/ruff_linter/src/rules/airflow/rules/moved_to_provider_in_3.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::importer::ImportRequest;
2-
use crate::rules::airflow::helpers::ProviderReplacement;
2+
use crate::rules::airflow::helpers::{is_guarded_by_try_except, ProviderReplacement};
33
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
44
use ruff_macros::{derive_message_formats, ViolationMetadata};
55
use ruff_python_ast::{Expr, ExprAttribute};
@@ -937,13 +937,17 @@ fn check_names_moved_to_provider(checker: &Checker, expr: &Expr, ranged: TextRan
937937
ranged.range(),
938938
);
939939

940-
if let ProviderReplacement::AutoImport {
941-
module,
942-
name,
943-
provider: _,
944-
version: _,
945-
} = replacement
946-
{
940+
let semantic = checker.semantic();
941+
if let Some((module, name)) = match &replacement {
942+
ProviderReplacement::AutoImport { module, name, .. } => Some((module, *name)),
943+
ProviderReplacement::SourceModuleMovedToProvider { module, name, .. } => {
944+
Some((module, name.as_str()))
945+
}
946+
_ => None,
947+
} {
948+
if is_guarded_by_try_except(expr, module, name, semantic) {
949+
return;
950+
}
947951
diagnostic.try_set_fix(|| {
948952
let (import_edit, binding) = checker.importer().get_or_import_symbol(
949953
&ImportRequest::import_from(module, name),
@@ -954,6 +958,5 @@ fn check_names_moved_to_provider(checker: &Checker, expr: &Expr, ranged: TextRan
954958
Ok(Fix::safe_edits(import_edit, [replacement_edit]))
955959
});
956960
}
957-
958961
checker.report_diagnostic(diagnostic);
959962
}

crates/ruff_linter/src/rules/airflow/rules/removal_in_3.rs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -865,19 +865,22 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) {
865865
_ => return,
866866
};
867867

868-
if is_guarded_by_try_except(expr, &replacement, semantic) {
869-
return;
870-
}
871-
872868
let mut diagnostic = Diagnostic::new(
873869
Airflow3Removal {
874870
deprecated: qualified_name.to_string(),
875871
replacement: replacement.clone(),
876872
},
877873
range,
878874
);
879-
880-
if let Replacement::AutoImport { module, name } = replacement {
875+
let semantic = checker.semantic();
876+
if let Some((module, name)) = match &replacement {
877+
Replacement::AutoImport { module, name } => Some((module, *name)),
878+
Replacement::SourceModuleMoved { module, name } => Some((module, name.as_str())),
879+
_ => None,
880+
} {
881+
if is_guarded_by_try_except(expr, module, name, semantic) {
882+
return;
883+
}
881884
diagnostic.try_set_fix(|| {
882885
let (import_edit, binding) = checker.importer().get_or_import_symbol(
883886
&ImportRequest::import_from(module, name),

crates/ruff_linter/src/rules/airflow/rules/suggested_to_move_to_provider_in_3.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::importer::ImportRequest;
22

3-
use crate::rules::airflow::helpers::ProviderReplacement;
3+
use crate::rules::airflow::helpers::{is_guarded_by_try_except, ProviderReplacement};
44
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
55
use ruff_macros::{derive_message_formats, ViolationMetadata};
66
use ruff_python_ast::{Expr, ExprAttribute};
@@ -279,13 +279,17 @@ fn check_names_moved_to_provider(checker: &Checker, expr: &Expr, ranged: TextRan
279279
ranged.range(),
280280
);
281281

282-
if let ProviderReplacement::AutoImport {
283-
module,
284-
name,
285-
provider: _,
286-
version: _,
287-
} = replacement
288-
{
282+
let semantic = checker.semantic();
283+
if let Some((module, name)) = match &replacement {
284+
ProviderReplacement::AutoImport { module, name, .. } => Some((module, *name)),
285+
ProviderReplacement::SourceModuleMovedToProvider { module, name, .. } => {
286+
Some((module, name.as_str()))
287+
}
288+
_ => None,
289+
} {
290+
if is_guarded_by_try_except(expr, module, name, semantic) {
291+
return;
292+
}
289293
diagnostic.try_set_fix(|| {
290294
let (import_edit, binding) = checker.importer().get_or_import_symbol(
291295
&ImportRequest::import_from(module, name),

crates/ruff_linter/src/rules/airflow/rules/suggested_to_update_3_0.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -283,10 +283,6 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) {
283283
_ => return,
284284
};
285285

286-
if is_guarded_by_try_except(expr, &replacement, semantic) {
287-
return;
288-
}
289-
290286
let mut diagnostic = Diagnostic::new(
291287
Airflow3SuggestedUpdate {
292288
deprecated: qualified_name.to_string(),
@@ -295,7 +291,15 @@ fn check_name(checker: &Checker, expr: &Expr, range: TextRange) {
295291
range,
296292
);
297293

298-
if let Replacement::AutoImport { module, name } = replacement {
294+
let semantic = checker.semantic();
295+
if let Some((module, name)) = match &replacement {
296+
Replacement::AutoImport { module, name } => Some((module, *name)),
297+
Replacement::SourceModuleMoved { module, name } => Some((module, name.as_str())),
298+
_ => None,
299+
} {
300+
if is_guarded_by_try_except(expr, module, name, semantic) {
301+
return;
302+
}
299303
diagnostic.try_set_fix(|| {
300304
let (import_edit, binding) = checker.importer().get_or_import_symbol(
301305
&ImportRequest::import_from(module, name),

0 commit comments

Comments
 (0)