Skip to content

Commit 1ba8b6b

Browse files
committed
feat(AIR302): add autofix to the cases that only paths have been changed
1 parent 6ac1647 commit 1ba8b6b

22 files changed

+1276
-109
lines changed

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

+10-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use crate::rules::numpy::helpers::{AttributeSearcher, ImportSearcher};
22
use ruff_python_ast::name::QualifiedNameBuilder;
33
use ruff_python_ast::statement_visitor::StatementVisitor;
44
use ruff_python_ast::visitor::Visitor;
5-
use ruff_python_ast::{Expr, ExprName, StmtTry};
5+
use ruff_python_ast::{Expr, ExprAttribute, ExprName, StmtTry};
66
use ruff_python_semantic::Exceptions;
77
use ruff_python_semantic::SemanticModel;
88

@@ -163,3 +163,12 @@ pub(crate) fn is_airflow_builtin_or_provider(
163163
_ => false,
164164
}
165165
}
166+
167+
/// Return the [`ast::ExprName`] at the head of the expression, if any.
168+
pub(crate) fn match_head(value: &Expr) -> Option<&ExprName> {
169+
match value {
170+
Expr::Attribute(ExprAttribute { value, .. }) => match_head(value),
171+
Expr::Name(name) => Some(name),
172+
_ => None,
173+
}
174+
}

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

+33-11
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
use crate::importer::ImportRequest;
2-
use crate::rules::airflow::helpers::{is_guarded_by_try_except, ProviderReplacement};
1+
use crate::checkers::ast::Checker;
2+
use crate::fix::edits::remove_unused_imports;
3+
use crate::rules::airflow::helpers::{is_guarded_by_try_except, match_head, ProviderReplacement};
34
use ruff_diagnostics::{Diagnostic, Edit, Fix, FixAvailability, Violation};
45
use ruff_macros::{derive_message_formats, ViolationMetadata};
56
use ruff_python_ast::{Expr, ExprAttribute};
67
use ruff_python_semantic::Modules;
8+
use ruff_python_semantic::{MemberNameImport, NameImport};
79
use ruff_text_size::Ranged;
810
use ruff_text_size::TextRange;
911

10-
use crate::checkers::ast::Checker;
11-
1212
/// ## What it does
1313
/// Checks for uses of Airflow functions and values that have been moved to it providers.
1414
/// (e.g., apache-airflow-providers-fab)
@@ -970,19 +970,41 @@ fn check_names_moved_to_provider(checker: &Checker, expr: &Expr, ranged: TextRan
970970
ProviderReplacement::SourceModuleMovedToProvider { module, name, .. } => {
971971
Some((module, name.as_str()))
972972
}
973-
_ => None,
973+
ProviderReplacement::None => None,
974974
} {
975975
if is_guarded_by_try_except(expr, module, name, semantic) {
976976
return;
977977
}
978+
978979
diagnostic.try_set_fix(|| {
979-
let (import_edit, binding) = checker.importer().get_or_import_symbol(
980-
&ImportRequest::import_from(module, name),
980+
let head = match_head(expr);
981+
let binding = checker
982+
.semantic()
983+
.resolve_name(head.expect(""))
984+
.or_else(|| checker.semantic().lookup_symbol(&head.unwrap().id))
985+
.map(|id| checker.semantic().binding(id));
986+
let stmt = binding.expect("").statement(semantic);
987+
let remove_import_edit = remove_unused_imports(
988+
std::iter::once(name),
989+
stmt.expect(""),
990+
None,
991+
checker.locator(),
992+
checker.stylist(),
993+
checker.indexer(),
994+
);
995+
let import_edit = checker.importer().add_import(
996+
&NameImport::ImportFrom(MemberNameImport::member(
997+
(*module).to_string(),
998+
name.to_string(),
999+
)),
9811000
expr.start(),
982-
checker.semantic(),
983-
)?;
984-
let replacement_edit = Edit::range_replacement(binding, ranged.range());
985-
Ok(Fix::safe_edits(import_edit, [replacement_edit]))
1001+
);
1002+
1003+
let replacement_edit = Edit::range_replacement(name.to_string(), ranged.range());
1004+
Ok(Fix::unsafe_edits(
1005+
remove_import_edit.expect(""),
1006+
[import_edit, replacement_edit], // add_import_edit.into_edits(), //, replacement_edit],
1007+
))
9861008
});
9871009
}
9881010
checker.report_diagnostic(diagnostic);

crates/ruff_linter/src/rules/airflow/snapshots/ruff_linter__rules__airflow__tests__AIR302_AIR302_amazon.py.snap

+207-11
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
source: crates/ruff_linter/src/rules/airflow/mod.rs
33
---
4-
AIR302_amazon.py:23:1: AIR302 `airflow.hooks.S3_hook.S3Hook` is moved into `amazon` provider in Airflow 3.0;
4+
AIR302_amazon.py:23:1: AIR302 [*] `airflow.hooks.S3_hook.S3Hook` is moved into `amazon` provider in Airflow 3.0;
55
|
66
21 | from airflow.sensors.s3_key_sensor import S3KeySensor
77
22 |
@@ -11,7 +11,24 @@ AIR302_amazon.py:23:1: AIR302 `airflow.hooks.S3_hook.S3Hook` is moved into `amaz
1111
|
1212
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.hooks.s3.S3Hook` instead.
1313

14-
AIR302_amazon.py:24:1: AIR302 `airflow.hooks.S3_hook.provide_bucket_name` is moved into `amazon` provider in Airflow 3.0;
14+
Unsafe fix
15+
1 1 | from __future__ import annotations
16+
2 2 |
17+
3 3 | from airflow.hooks.S3_hook import (
18+
4 |- S3Hook,
19+
5 4 | provide_bucket_name,
20+
6 5 | )
21+
7 6 | from airflow.operators.gcs_to_s3 import GCSToS3Operator
22+
--------------------------------------------------------------------------------
23+
19 18 | S3ToRedshiftTransfer,
24+
20 19 | )
25+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
26+
21 |+from airflow.providers.amazon.aws.hooks.s3 import S3Hook
27+
22 22 |
28+
23 23 | S3Hook()
29+
24 24 | provide_bucket_name()
30+
31+
AIR302_amazon.py:24:1: AIR302 [*] `airflow.hooks.S3_hook.provide_bucket_name` is moved into `amazon` provider in Airflow 3.0;
1532
|
1633
23 | S3Hook()
1734
24 | provide_bucket_name()
@@ -21,7 +38,24 @@ AIR302_amazon.py:24:1: AIR302 `airflow.hooks.S3_hook.provide_bucket_name` is mov
2138
|
2239
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.hooks.s3.provide_bucket_name` instead.
2340

24-
AIR302_amazon.py:26:1: AIR302 `airflow.operators.gcs_to_s3.GCSToS3Operator` is moved into `amazon` provider in Airflow 3.0;
41+
Unsafe fix
42+
2 2 |
43+
3 3 | from airflow.hooks.S3_hook import (
44+
4 4 | S3Hook,
45+
5 |- provide_bucket_name,
46+
6 5 | )
47+
7 6 | from airflow.operators.gcs_to_s3 import GCSToS3Operator
48+
8 7 | from airflow.operators.google_api_to_s3_transfer import (
49+
--------------------------------------------------------------------------------
50+
19 18 | S3ToRedshiftTransfer,
51+
20 19 | )
52+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
53+
21 |+from airflow.providers.amazon.aws.hooks.s3 import provide_bucket_name
54+
22 22 |
55+
23 23 | S3Hook()
56+
24 24 | provide_bucket_name()
57+
58+
AIR302_amazon.py:26:1: AIR302 [*] `airflow.operators.gcs_to_s3.GCSToS3Operator` is moved into `amazon` provider in Airflow 3.0;
2559
|
2660
24 | provide_bucket_name()
2761
25 |
@@ -32,7 +66,24 @@ AIR302_amazon.py:26:1: AIR302 `airflow.operators.gcs_to_s3.GCSToS3Operator` is m
3266
|
3367
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.transfers.gcs_to_s3.GCSToS3Operator` instead.
3468

35-
AIR302_amazon.py:28:1: AIR302 `airflow.operators.google_api_to_s3_transfer.GoogleApiToS3Operator` is moved into `amazon` provider in Airflow 3.0;
69+
Unsafe fix
70+
4 4 | S3Hook,
71+
5 5 | provide_bucket_name,
72+
6 6 | )
73+
7 |-from airflow.operators.gcs_to_s3 import GCSToS3Operator
74+
8 7 | from airflow.operators.google_api_to_s3_transfer import (
75+
9 8 | GoogleApiToS3Operator,
76+
10 9 | GoogleApiToS3Transfer,
77+
--------------------------------------------------------------------------------
78+
19 18 | S3ToRedshiftTransfer,
79+
20 19 | )
80+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
81+
21 |+from airflow.providers.amazon.aws.transfers.gcs_to_s3 import GCSToS3Operator
82+
22 22 |
83+
23 23 | S3Hook()
84+
24 24 | provide_bucket_name()
85+
86+
AIR302_amazon.py:28:1: AIR302 [*] `airflow.operators.google_api_to_s3_transfer.GoogleApiToS3Operator` is moved into `amazon` provider in Airflow 3.0;
3687
|
3788
26 | GCSToS3Operator()
3889
27 |
@@ -42,7 +93,24 @@ AIR302_amazon.py:28:1: AIR302 `airflow.operators.google_api_to_s3_transfer.Googl
4293
|
4394
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.transfers.google_api_to_s3.GoogleApiToS3Operator` instead.
4495

45-
AIR302_amazon.py:29:1: AIR302 `airflow.operators.google_api_to_s3_transfer.GoogleApiToS3Transfer` is moved into `amazon` provider in Airflow 3.0;
96+
Unsafe fix
97+
6 6 | )
98+
7 7 | from airflow.operators.gcs_to_s3 import GCSToS3Operator
99+
8 8 | from airflow.operators.google_api_to_s3_transfer import (
100+
9 |- GoogleApiToS3Operator,
101+
10 9 | GoogleApiToS3Transfer,
102+
11 10 | )
103+
12 11 | from airflow.operators.redshift_to_s3_operator import (
104+
--------------------------------------------------------------------------------
105+
19 18 | S3ToRedshiftTransfer,
106+
20 19 | )
107+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
108+
21 |+from airflow.providers.amazon.aws.transfers.google_api_to_s3 import GoogleApiToS3Operator
109+
22 22 |
110+
23 23 | S3Hook()
111+
24 24 | provide_bucket_name()
112+
113+
AIR302_amazon.py:29:1: AIR302 [*] `airflow.operators.google_api_to_s3_transfer.GoogleApiToS3Transfer` is moved into `amazon` provider in Airflow 3.0;
46114
|
47115
28 | GoogleApiToS3Operator()
48116
29 | GoogleApiToS3Transfer()
@@ -52,7 +120,33 @@ AIR302_amazon.py:29:1: AIR302 `airflow.operators.google_api_to_s3_transfer.Googl
52120
|
53121
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.transfers.google_api_to_s3.GoogleApiToS3Operator` instead.
54122

55-
AIR302_amazon.py:31:1: AIR302 `airflow.operators.redshift_to_s3_operator.RedshiftToS3Operator` is moved into `amazon` provider in Airflow 3.0;
123+
Unsafe fix
124+
6 6 | )
125+
7 7 | from airflow.operators.gcs_to_s3 import GCSToS3Operator
126+
8 8 | from airflow.operators.google_api_to_s3_transfer import (
127+
9 |- GoogleApiToS3Operator,
128+
10 9 | GoogleApiToS3Transfer,
129+
11 10 | )
130+
12 11 | from airflow.operators.redshift_to_s3_operator import (
131+
--------------------------------------------------------------------------------
132+
19 18 | S3ToRedshiftTransfer,
133+
20 19 | )
134+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
135+
21 |+from airflow.providers.amazon.aws.transfers.google_api_to_s3 import GoogleApiToS3Operator
136+
22 22 |
137+
23 23 | S3Hook()
138+
24 24 | provide_bucket_name()
139+
--------------------------------------------------------------------------------
140+
26 26 | GCSToS3Operator()
141+
27 27 |
142+
28 28 | GoogleApiToS3Operator()
143+
29 |-GoogleApiToS3Transfer()
144+
29 |+GoogleApiToS3Operator()
145+
30 30 |
146+
31 31 | RedshiftToS3Operator()
147+
32 32 | RedshiftToS3Transfer()
148+
149+
AIR302_amazon.py:31:1: AIR302 [*] `airflow.operators.redshift_to_s3_operator.RedshiftToS3Operator` is moved into `amazon` provider in Airflow 3.0;
56150
|
57151
29 | GoogleApiToS3Transfer()
58152
30 |
@@ -62,7 +156,24 @@ AIR302_amazon.py:31:1: AIR302 `airflow.operators.redshift_to_s3_operator.Redshif
62156
|
63157
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.transfers.redshift_to_s3.RedshiftToS3Operator` instead.
64158

65-
AIR302_amazon.py:32:1: AIR302 `airflow.operators.redshift_to_s3_operator.RedshiftToS3Transfer` is moved into `amazon` provider in Airflow 3.0;
159+
Unsafe fix
160+
10 10 | GoogleApiToS3Transfer,
161+
11 11 | )
162+
12 12 | from airflow.operators.redshift_to_s3_operator import (
163+
13 |- RedshiftToS3Operator,
164+
14 13 | RedshiftToS3Transfer,
165+
15 14 | )
166+
16 15 | from airflow.operators.s3_file_transform_operator import S3FileTransformOperator
167+
--------------------------------------------------------------------------------
168+
19 18 | S3ToRedshiftTransfer,
169+
20 19 | )
170+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
171+
21 |+from airflow.providers.amazon.aws.transfers.redshift_to_s3 import RedshiftToS3Operator
172+
22 22 |
173+
23 23 | S3Hook()
174+
24 24 | provide_bucket_name()
175+
176+
AIR302_amazon.py:32:1: AIR302 [*] `airflow.operators.redshift_to_s3_operator.RedshiftToS3Transfer` is moved into `amazon` provider in Airflow 3.0;
66177
|
67178
31 | RedshiftToS3Operator()
68179
32 | RedshiftToS3Transfer()
@@ -72,7 +183,33 @@ AIR302_amazon.py:32:1: AIR302 `airflow.operators.redshift_to_s3_operator.Redshif
72183
|
73184
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.transfers.redshift_to_s3.RedshiftToS3Operator` instead.
74185

75-
AIR302_amazon.py:34:1: AIR302 `airflow.operators.s3_file_transform_operator.S3FileTransformOperator` is moved into `amazon` provider in Airflow 3.0;
186+
Unsafe fix
187+
10 10 | GoogleApiToS3Transfer,
188+
11 11 | )
189+
12 12 | from airflow.operators.redshift_to_s3_operator import (
190+
13 |- RedshiftToS3Operator,
191+
14 13 | RedshiftToS3Transfer,
192+
15 14 | )
193+
16 15 | from airflow.operators.s3_file_transform_operator import S3FileTransformOperator
194+
--------------------------------------------------------------------------------
195+
19 18 | S3ToRedshiftTransfer,
196+
20 19 | )
197+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
198+
21 |+from airflow.providers.amazon.aws.transfers.redshift_to_s3 import RedshiftToS3Operator
199+
22 22 |
200+
23 23 | S3Hook()
201+
24 24 | provide_bucket_name()
202+
--------------------------------------------------------------------------------
203+
29 29 | GoogleApiToS3Transfer()
204+
30 30 |
205+
31 31 | RedshiftToS3Operator()
206+
32 |-RedshiftToS3Transfer()
207+
32 |+RedshiftToS3Operator()
208+
33 33 |
209+
34 34 | S3FileTransformOperator()
210+
35 35 |
211+
212+
AIR302_amazon.py:34:1: AIR302 [*] `airflow.operators.s3_file_transform_operator.S3FileTransformOperator` is moved into `amazon` provider in Airflow 3.0;
76213
|
77214
32 | RedshiftToS3Transfer()
78215
33 |
@@ -83,7 +220,22 @@ AIR302_amazon.py:34:1: AIR302 `airflow.operators.s3_file_transform_operator.S3Fi
83220
|
84221
= help: Install `apache-airflow-providers-amazon>=3.0.0` and use `airflow.providers.amazon.aws.operators.s3.S3FileTransformOperator` instead.
85222

86-
AIR302_amazon.py:36:1: AIR302 `airflow.operators.s3_to_redshift_operator.S3ToRedshiftOperator` is moved into `amazon` provider in Airflow 3.0;
223+
Unsafe fix
224+
13 13 | RedshiftToS3Operator,
225+
14 14 | RedshiftToS3Transfer,
226+
15 15 | )
227+
16 |-from airflow.operators.s3_file_transform_operator import S3FileTransformOperator
228+
17 16 | from airflow.operators.s3_to_redshift_operator import (
229+
18 17 | S3ToRedshiftOperator,
230+
19 18 | S3ToRedshiftTransfer,
231+
20 19 | )
232+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
233+
21 |+from airflow.providers.amazon.aws.operators.s3 import S3FileTransformOperator
234+
22 22 |
235+
23 23 | S3Hook()
236+
24 24 | provide_bucket_name()
237+
238+
AIR302_amazon.py:36:1: AIR302 [*] `airflow.operators.s3_to_redshift_operator.S3ToRedshiftOperator` is moved into `amazon` provider in Airflow 3.0;
87239
|
88240
34 | S3FileTransformOperator()
89241
35 |
@@ -93,7 +245,20 @@ AIR302_amazon.py:36:1: AIR302 `airflow.operators.s3_to_redshift_operator.S3ToRed
93245
|
94246
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.transfers.s3_to_redshift.S3ToRedshiftOperator` instead.
95247

96-
AIR302_amazon.py:37:1: AIR302 `airflow.operators.s3_to_redshift_operator.S3ToRedshiftTransfer` is moved into `amazon` provider in Airflow 3.0;
248+
Unsafe fix
249+
15 15 | )
250+
16 16 | from airflow.operators.s3_file_transform_operator import S3FileTransformOperator
251+
17 17 | from airflow.operators.s3_to_redshift_operator import (
252+
18 |- S3ToRedshiftOperator,
253+
19 18 | S3ToRedshiftTransfer,
254+
20 19 | )
255+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
256+
21 |+from airflow.providers.amazon.aws.transfers.s3_to_redshift import S3ToRedshiftOperator
257+
22 22 |
258+
23 23 | S3Hook()
259+
24 24 | provide_bucket_name()
260+
261+
AIR302_amazon.py:37:1: AIR302 [*] `airflow.operators.s3_to_redshift_operator.S3ToRedshiftTransfer` is moved into `amazon` provider in Airflow 3.0;
97262
|
98263
36 | S3ToRedshiftOperator()
99264
37 | S3ToRedshiftTransfer()
@@ -103,11 +268,42 @@ AIR302_amazon.py:37:1: AIR302 `airflow.operators.s3_to_redshift_operator.S3ToRed
103268
|
104269
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.transfers.s3_to_redshift.S3ToRedshiftOperator` instead.
105270

106-
AIR302_amazon.py:39:1: AIR302 `airflow.sensors.s3_key_sensor.S3KeySensor` is moved into `amazon` provider in Airflow 3.0;
271+
Unsafe fix
272+
15 15 | )
273+
16 16 | from airflow.operators.s3_file_transform_operator import S3FileTransformOperator
274+
17 17 | from airflow.operators.s3_to_redshift_operator import (
275+
18 |- S3ToRedshiftOperator,
276+
19 18 | S3ToRedshiftTransfer,
277+
20 19 | )
278+
21 20 | from airflow.sensors.s3_key_sensor import S3KeySensor
279+
21 |+from airflow.providers.amazon.aws.transfers.s3_to_redshift import S3ToRedshiftOperator
280+
22 22 |
281+
23 23 | S3Hook()
282+
24 24 | provide_bucket_name()
283+
--------------------------------------------------------------------------------
284+
34 34 | S3FileTransformOperator()
285+
35 35 |
286+
36 36 | S3ToRedshiftOperator()
287+
37 |-S3ToRedshiftTransfer()
288+
37 |+S3ToRedshiftOperator()
289+
38 38 |
290+
39 39 | S3KeySensor()
291+
292+
AIR302_amazon.py:39:1: AIR302 [*] `airflow.sensors.s3_key_sensor.S3KeySensor` is moved into `amazon` provider in Airflow 3.0;
107293
|
108294
37 | S3ToRedshiftTransfer()
109295
38 |
110296
39 | S3KeySensor()
111297
| ^^^^^^^^^^^ AIR302
112298
|
113299
= help: Install `apache-airflow-providers-amazon>=1.0.0` and use `airflow.providers.amazon.aws.sensors.s3.S3KeySensor` instead.
300+
301+
Unsafe fix
302+
18 18 | S3ToRedshiftOperator,
303+
19 19 | S3ToRedshiftTransfer,
304+
20 20 | )
305+
21 |-from airflow.sensors.s3_key_sensor import S3KeySensor
306+
21 |+from airflow.providers.amazon.aws.sensors.s3 import S3KeySensor
307+
22 22 |
308+
23 23 | S3Hook()
309+
24 24 | provide_bucket_name()

0 commit comments

Comments
 (0)